using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using BrainTechLLC.ThreadSafeObjects;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Net.Sockets;
using BrainTechLLC;


namespace Mud.EmlenMudMain
{
    public class CharacterData : GameThingBaseClass
    {
        public CharacterData() { }

        public GameChar ToGameChar(Dictionary<int, GameCharTemplate> charTemplates, Dictionary<int, GameLocation> locs)
        {
            // TODO
            GameChar chr = new GameChar();
            
            if (Copper > 0)
                chr.AddOrSetProperty("Copper", Copper);
            
            if ((long)CurrentlyAffectedBy != 0)
                chr.AddOrSetProperty("CurrentlyAffectedBy", CurrentlyAffectedBy);
            
            chr.AddOrSetProperty("DamageRoll", DamageRoll);
            
            if (DelayedUntil != DateTime.MinValue)
                chr.AddOrSetProperty("DelayedUntil", DelayedUntil);
            
            chr.Name = new NameAndDescription() { Description = this.Description, ShortDescription = this.Title, Name = this.ShortName, Keywords = this.Keywords };
            
            if (this.Experience != 0)
                chr.AddOrSetProperty("Experience", Experience);
            
            if ((int)this.OptionsToUseWhileFighting != 0)
                chr.AddOrSetProperty("OptionsToUseWhileFighting", (int)this.OptionsToUseWhileFighting);
            if (this.LastMovementTime != DateTime.MinValue)
                chr.AddOrSetProperty("LastMovementTime", this.LastMovementTime);
            if (this.FleeWhenHPBelow > 0)
                chr.AddOrSetProperty("FleeWhenHPBelow", this.FleeWhenHPBelow);
            if (Gold > 0)
                chr.AddOrSetProperty("Gold", this.Gold);
            
            if (this.height != 0)
                chr.AddOrSetProperty("Height", this.height);
            
            chr.AddOrSetProperty("Hitroll", this.Hitroll);
            chr.AddOrSetProperty("HitPoints", this.HPCurrent);
            chr.AddOrSetProperty("MaxHitPoints", this.HPMax);
            
            if (MobSelfDestructsAt != DateTime.MaxValue)
                chr.AddOrSetProperty("MobSelfDestructsAt", this.MobSelfDestructsAt);
            
            chr.AddOrSetProperty("MovementPoints", this.MPCurrent);
            chr.AddOrSetProperty("MaxMovementPoints", this.MPMax);
            chr.AddOrSetProperty("NaturalArmor", this.NaturalArmor);
            chr.AddOrSetProperty("Position", this.position);
            
            if (this.RemortTimes > 0)
                chr.AddOrSetProperty("RemortTimes", this.RemortTimes);
            
            chr.AddOrSetProperty("Sex", (int)this.sex);
            chr.AddOrSetProperty("TempFlags", (long)this.TempFlags);
            
            if (this.vnumInRoom > 0)
                chr.AddOrSetProperty("InRoomVNUM", this.vnumInRoom);
            
            if (this.VnumMobPrototype > 0)
                chr.AddOrSetProperty("VnumMobPrototype", this.VnumMobPrototype);
            
            if (this.wait > 0)
                chr.AddOrSetProperty("Wait", this.wait);

            if (this.WizInvisLevel > 0)
                chr.AddOrSetProperty("WizInvisLevel", this.WizInvisLevel);

            if (this.pcdata != null)
            {
                this.pcdata.ToGameChar(chr);
            }

            Dictionary<int, long> map = new Dictionary<int, long>();

            if (this.vnumMobPrototype > 0)
            {
                long id;
                if (!map.TryGetValue(this.vnumMobPrototype, out id))
                {
                    var t = GameCharTemplate.FindCharTemplateByVnum(this.vnumMobPrototype, charTemplates);

                    if (t != null)
                        id = t.AssociatedID;

                    map.Add(this.vnumMobPrototype, id);
                }
                chr.TemplateID = id;
            }

            Dictionary<int, GameLocation> map2 = new Dictionary<int, GameLocation>();

            if (this.vnumInRoom > 0)
            {
                GameLocation ll;
                if (!map2.TryGetValue(this.vnumInRoom, out ll))
                {
                    ll = GameLocation.FindLocationByVnum(this.vnumInRoom, locs);
                    map2.Add(this.vnumInRoom, ll);
                }
                if (ll != null)
                {
                    chr.Location = ll.AssociatedID;
                    chr.LocationInt = new LocationInt(ll.XYZ);
                }
            }

            chr.Register();
            return chr;
        }

        public CharacterData(bool fIsPlayer)
        {
            if (fIsPlayer) pcdataInternal = new PlayerData();
        }

#if NO_SILVERLIGHT
        [NonSerialized]
#endif
        protected IFightData fightInfoInternal = null;
#if NO_SILVERLIGHT
        [NonSerialized]
#endif
        protected MobPrototypeData mobPrototypeInternal = null;
#if NO_SILVERLIGHT
        [NonSerialized]
#endif
        protected RoomData inRoomInternal = null;
#if NO_SILVERLIGHT
        [NonSerialized]
#endif
        protected CharacterData originalInternal = null;
#if NO_SILVERLIGHT
        [NonSerialized]
        protected IDescriptorData descriptorInternal = null;
#endif
        protected PlayerData pcdataInternal = null;
        /// <summary>
        /// Actual height of the character, not to be accessed directly
        /// </summary>
        protected int heightInternal = 0;
        protected int vnumMobPrototype = 0;
        protected int vnumInRoomInternal = 0;
        [NonSerialized]
        protected List<long> senttells = null;
        protected CombatSettings cmbatOptions = CombatSettings.None;
        protected ActionsAndBehavior currentActionsAndBehavior = ActionsAndBehavior.NONE;
        protected long currentlyAffectedBy = (long)EffectType.NONE;
        protected TempStatusFlags tempFlags = TempStatusFlags.NONE;
        protected CharPosition positionActual = CharPosition.standing;
        protected int MPCurrentt = 0;
        protected int hitroll = 0;
        protected string description = "";
        protected int fleeWhenHPBelow = 0;
        protected DateTime mobSelfDestructsAt = DateTime.MaxValue;
        /// <summary>
        /// If the character is to be delayed in their next
        /// action, this will store the time at which they 
        /// will no longer be delayed
        /// </summary>
        protected DateTime CannotPerformNextActionUntil = DateTime.MinValue;
        protected DateTime dtLastMovement = DateTime.MinValue;
        [NonSerialized]
        protected Queue<string> rgMovementCommands = new Queue<string>(4);
        protected List<long> effectsAffectedBy = new List<long>();
        protected List<ObjectData> carryingObjects = new List<ObjectData>();
        protected int naturalArmor = 0;
        protected int damageRoll = 0;
        protected long copper = 0;
        protected long gold = 0;
        protected long experience = 0;
        protected int wait = 0;
        protected int MPMaxx = 0;
        protected int HPCurrentt = 0;
        protected int HPMaxx = 0;

        /// <summary>
        /// Fight data structure
        /// </summary>
        public IFightData FightInfoInternal
        {
            get { return fightInfoInternal; }
        }

        /// <summary>
        /// In-Room RoomData reference
        /// </summary>
        public RoomData InRoomInternal
        {
            get { return inRoomInternal; }
            set { inRoomInternal = value; }
        }

        /// <summary>
        /// Internally maintained original characterdata for switching
        /// </summary>
        public CharacterData OriginalInternal
        {
            get { return originalInternal; }
            set { originalInternal = value; }
        }

        /// <summary>
        /// The mob prototype vnum upon which this mob is based
        /// </summary>
        public int VnumMobPrototype
        {
            get { return vnumMobPrototype; }
            set { vnumMobPrototype = value; }
        }

        /// <summary>
        /// Last few unique dynamic ID who sent him/her a tell
        /// </summary>
        public List<long> SentTellsToCharacter
        {
            get { return senttells; }
            set { senttells = value; }
        }
        /// <summary>
        /// Options to use while chAttacking
        /// </summary>
        public CombatSettings OptionsToUseWhileFighting
        {
            get { return cmbatOptions; }
            set { cmbatOptions = value; }
        }

        /// <summary>
        /// Current actions and behaviors
        /// </summary>
        public ActionsAndBehavior CurrentActionsAndBehavior
        {
            get { return currentActionsAndBehavior; }
            set { currentActionsAndBehavior = value; }
        }

        /// <summary>
        /// Currently affected by
        /// </summary>
        public long CurrentlyAffectedBy
        {
            get { return currentlyAffectedBy; }
            set { currentlyAffectedBy = value; }
        }

        /// <summary>
        /// Temporary flags for book-keeping
        /// </summary>
        public TempStatusFlags TempFlags
        {
            get { return tempFlags; }
            set { tempFlags = value; }
        }
        /// <summary>
        /// Position the character is currently in
        /// </summary>
        public CharPosition position
        {
            get
            {
                return positionActual;
            }
            set
            {
                // actually check HP here, etc... make sure they aren't dead
                positionActual = value;
            }
        }

        /// <summary>
        /// Character (long) description
        /// </summary>
        public string Description
        {
            get { return description; }
            set { description = value; }
        }

        /// <summary>
        /// Flee at this many HPCurrent points
        /// </summary>
        public int FleeWhenHPBelow
        {
            get { return fleeWhenHPBelow; }
            set { fleeWhenHPBelow = value; }
        }

        /// <summary>
        /// Time at which a mob self destructs
        /// </summary>
        public DateTime MobSelfDestructsAt
        {
            get { return mobSelfDestructsAt; }
            set { mobSelfDestructsAt = value; }
        }

        /// <summary>
        /// Maximum hit points
        /// </summary>
        public int HPMax
        {
            get { return HPMaxx; }
            set { HPMaxx = value; }
        }
        /// <summary>
        /// Current hit points
        /// </summary>
        public int HPCurrent
        {
            get { return HPCurrentt; }
            set
            {
                HPCurrentt = value;
            }
        }
        /// <summary>
        /// Maximum movement points
        /// </summary>
        public int MPMax
        {
            get { return MPMaxx; }
            set { MPMaxx = value; }
        }
        /// <summary>
        /// Current movement points
        /// </summary>
        public int MPCurrent
        {
            get { return MPCurrentt; }
            set { MPCurrentt = value; }
        }

        /// <summary>
        /// Hitroll
        /// </summary>
        public int Hitroll
        {
            get { return hitroll; }
            set { hitroll = value; }
        }

        /// <summary>
        /// Damage roll
        /// </summary>
        public int DamageRoll
        {
            get { return damageRoll; }
            set { damageRoll = value; }
        }

        /// <summary>
        /// General skin/natural armor
        /// </summary>
        public int NaturalArmor
        {
            get { return naturalArmor; }
            set { naturalArmor = value; }
        }

        /// <summary>
        /// CopperCoins coins
        /// </summary>
        public long Copper
        {
            get { return copper; }
            set { copper = value; }
        }

        /// <summary>
        /// GoldCoins coins
        /// </summary>
        public long Gold
        {
            get { return gold; }
            set { gold = value; }
        }

        /// <summary>
        /// Experience
        /// </summary>
        public long Experience
        {
            get { return experience; }
            set { experience = value; }
        }
        /// <summary>
        /// Wait state (?)
        /// </summary>
        public int Wait
        {
            get { return wait; }
            set { wait = value; }
        }

        /* OLD script format */
        // public int cur_line;		/*The scriptline that just was run */
        // public int scr_wait;		/*Wait for the script to continue */
        // public int wait_type;	/*How "wait" is counted down */

        /// <summary>
        /// Effects currently attached to the character (Array of EffectData)
        /// These are effects attached via objects, spells, etc, and need
        /// to be checked occasionally
        /// </summary>
        protected List<long> EffectsAffectedBy
        {
            get { return effectsAffectedBy; }
            set { effectsAffectedBy = value; }
        }

        /// <summary>
        /// Objects currently carried by the character (Array of ObjectData)
        /// This includes inventory items (I think it will, at this point
        /// at least)
        /// </summary>
        public List<ObjectData> CarryingObjects
        {
            get { return carryingObjects; }
            set { carryingObjects = value; }
        }

        /// <summary>
        /// The currentRoom vnum in which this character exists (0 = not placed)
        /// </summary>
        public int vnumInRoom { get { return vnumInRoomInternal; } }

        public PlayerData pcdata { get { return pcdataInternal; } }

        /// <summary>
        /// This queues movement commands if they are typed
        /// in very quickly, etc
        /// </summary>
        public Queue<string> QueueOfMovementCommands
        {
            get { return rgMovementCommands; }
            set { rgMovementCommands = value; }
        }

        public bool IsFighting { get { return (FightInfoInternal != null); } }
        public bool IsFightOptionSet(CombatSettings fightOption) { return ((OptionsToUseWhileFighting & fightOption) != 0); }
        public bool IsMob { get { return (mobPrototype != null); } }
        public bool IsPlayer { get { return (pcdata != null); } }
        public string MobOrPlayer { get { return IsMob ? ("mob vnum " + mobPrototype.Vnum) : (IsPlayer ? "player" : "unknown"); } }
        public bool IsCurrentlyAffectedBy(EffectType eff) { return ((currentlyAffectedBy & (long)eff) != 0); }
        public void InternalSetInRoomVnum(int vnum) { vnumInRoomInternal = vnum; }

        public IFightData FightInfo
        {
            get
            {
                if (fightInfoInternal == null) fightInfoInternal = new FightData();
                return fightInfoInternal;
            }
            set
            {
                if (value == null)
                {
                    // Do other stuff here too
                    fightInfoInternal = null;
                    position = CharPosition.standing;
                }
            }
        }

        public ObjectData Wielding
        {
            get
            {
                // TODO: HEREHERE
                return null;
            }
            set
            {
                // TODO: HEREHERE
            }
        }

        public void DisplayLostLink()
        {
            // HEREHERE
            RoomData room = EmlenMud.GetInRoom(this);
            if (room != null)
            {
                EmlenMud.SendToOthersWhoCanSee(this, room, "|ShortName is no longer connected...\n\r");
            }
        }

        public virtual bool IsConsideredEnemyOf(CharacterData chrOther)
        {
            // TODO: implement for mobs and players
            return true;
        }

        public RoomData InSameRoomAs(CharacterData chrOther)
        {
            if (EmlenMud.GetInRoom(this) == null || chrOther == null) return null;
            if (EmlenMud.GetInRoom(this) != EmlenMud.GetInRoom(chrOther)) return null;
            return EmlenMud.GetInRoom(this);
        }

        /// <summary>
        /// Given the current conditions, can the character fly right now?
        /// </summary>
        /// <returns></returns>
        public bool CanFlyRightNow()
        {
            if (EmlenMud.GetInRoom(this) == null) return false;
            if (!HasGeneralAbilityToFly()) return false;
            if (EmlenMud.GetInRoom(this).Indoors) return false;
            // More conditions here?
            return true;
        }

        public string ReasonCantFlyRightNow()
        {
            if (!HasGeneralAbilityToFly()) return "You don't have the ability to fly.";
            if (EmlenMud.GetInRoom(this).Indoors) return "You can't fly because you are indoors.";
            return "You are able to fly.";
        }

        public bool HasSpecialAbility(PlayerSpecialBits sbits, EffectType eff)
        {
            if (IsPlayer)
            {
                if (((PlayerData)pcdata).HasSpecialBits(sbits)) return true;
                if ((pcdata.Effects1 & (long)eff) != 0) return true;
            }
            else if (IsMob)
            {
                if (((MobPrototype)mobPrototype).HasPrototypeEffects(eff)) return true;
            }
            return false;
        }

        /// <summary>
        /// In general, does this character have the ability to fly?
        /// </summary>
        /// <returns></returns>
        public bool HasGeneralAbilityToFly()
        {
            return HasSpecialAbility(PlayerSpecialBits.HOLYWALK, EffectType.FLYING);
        }

        /// <summary>
        /// Gets or sets whether the character is flying, taking into
        /// account whether or not they can at the moment
        /// </summary>
        public bool Flying
        {
            get { return IsCurrentlyAffectedBy(EffectType.FLYING); }
            set
            {
                if (!CanFlyRightNow()) return;
                if (value == false) CurrentlyAffectedBy &= (~((long)EffectType.FLYING));
                else CurrentlyAffectedBy |= (long)EffectType.FLYING;
            }
        }

        /// <summary>
        /// Determines if the character has the ability to see in the
        /// dark, in general
        /// </summary>
        /// <returns></returns>
        public bool HasAbilityToSeeInDark()
        {
            if (HasSpecialAbility(PlayerSpecialBits.HOLYLIGHT, EffectType.INFRARED)) return true;
            return false;
        }

        /// <summary>
        /// Determines if this character can see an other character
        /// </summary>
        /// <param name="chrOther">The other character</param>
        /// <returns></returns>
        public bool CanSee(CharacterData chrOther)
        {
            if (this == chrOther) return true;  // you can always see yourself
            if (EmlenMud.GetInRoom(this) == null) return false;
            if (chrOther.WizInvisLevel > Level) return false;
            if (HolyLight) return true;
            if (!CanSee()) return false;
            if (EmlenMud.GetInRoom(this).IsDark() && !HasAbilityToSeeInDark()) return false;
            if (chrOther.IsCurrentlyAffectedBy(EffectType.INVISIBLE) && !CanSeeInvis()) return false;
            if (chrOther.IsCurrentlyAffectedBy(EffectType.HIDE) && !CanSeeHidden()) return false;
            return true;
        }

        /// <summary>
        /// Determines if this character can see door data
        /// </summary>
        /// <param name="door"></param>
        /// <returns></returns>
        public bool CanSee(DoorData door)
        {
            if (HolyLight) return true;
            if (!CanSee()) return false;
            if (door.FlagSet(ExitFlags.HIDDEN) && !CanSeeHidden()) return false;
            return true;
        }

        public bool CanSee(ExitData ex)
        {
            if (ex.D_info != null) return CanSee((DoorData)ex.D_info);
            if (HolyLight) return true;
            if (!CanSee()) return false;
            return true;
        }

        /// <summary>
        /// Can the character currently detect hidden 'stuff'?
        /// </summary>
        /// <returns></returns>
        public bool CanSeeHidden()
        {
            if (HolyLight) return true;
            return IsCurrentlyAffectedBy(EffectType.DETECT_HIDDEN);
        }

        /// <summary>
        /// Does the character currently have the ability to detect invis?
        /// </summary>
        /// <returns></returns>
        public bool CanSeeInvis()
        {
            if (HolyLight) return true;
            return IsCurrentlyAffectedBy(EffectType.DETECT_INVIS);
        }

        /// <summary>
        /// Can the character even see at all????
        /// </summary>
        /// <returns></returns>
        public bool CanSee()
        {
            if (HolyLight) return true;
            if (IsCurrentlyAffectedBy(EffectType.BLIND)) return false;
            return true;
        }

        /// <summary>
        /// Can the character see in the given currentRoom?
        /// </summary>
        /// <param name="currentRoom">the currentRoom the character is trying to see</param>
        /// <returns>true or false.  If false, call currentRoom.GetReasonWhyCharacterCantSeeInRoom(this)
        /// for a textual reason why the character can't see in this currentRoom</returns>
        public bool CanSee(RoomData room)
        {
            if (HolyLight) return true;
            if (!CanSee()) return false;
            if (room.IsDark() == true && HasAbilityToSeeInDark() == false) return false;
            if (EmlenMud.DynamicWorld.WeatherInfo.Sky == SkyWeather.SKY_FOGGY &&
                room.Indoors == false &&
                Rand.RandIntBetween(0, 10) > 5) return false;
            return true;
        }

        public new string ShortDescription
        {
            get
            {
                if (IsMob) { return (mobPrototype.Long_descr == null) ? "" : mobPrototype.Long_descr; }
                else if (IsPlayer) { return pcdata.Short_descr == null ? "" : pcdata.Short_descr; }
                else return "";
            }
            set
            {
            }
        }

        public string LongDescription
        {
            get
            {
                if (IsMob) { return (mobPrototype.Description == null) ? "" : mobPrototype.Description; }
                else if (IsPlayer) { return (Description == null) ? "" : Description; }
                else return "";
            }
            set
            {
                if (IsMob) { mobPrototype.Description = (value == null) ? "" : value; }
                else if (IsPlayer) { Description = (value == null) ? "" : value; }
            }
        }

#if NO_SILVERLIGHT
        /// <summary>
        /// The socket connection information (or web connection information)
        /// associated with this character
        /// </summary>
        public IDescriptorData descriptor
        {
            get { return descriptorInternal; }
            set { descriptorInternal = value; }
        }
#endif

        public int this[StoredFightData fdataIndex]
        {
            get { if (!IsFighting) return 0; else return FightInfo[fdataIndex]; }
            set { FightInfo[fdataIndex] = value; }
        }

        public Sex sex
        {
            get
            {
                if (IsPlayer)
                {
                    return pcdata.PSex;
                }
                if (IsMob)
                {
                    return mobPrototype.Sex;
                }
                return Sex.NEUTRAL;
            }
        }



        /// <summary>
        /// This stores when the character last moved
        /// </summary>    
        public DateTime LastMovementTime
        {
            get { return dtLastMovement; }
            set { dtLastMovement = value; }
        }

        /// <summary>
        /// Gets the level of the character (whether player or mob)
        /// </summary>
        public int Level
        {
            get
            {
                if (pcdata != null)
                {
                    return pcdata.Level;
                }
                else if (mobPrototype != null)
                {
                    return mobPrototype.Level;
                }
                else return 1;
            }
        }

        /// <summary>
        /// Gets or sets the mob prototype upon which this character is 
        /// based.  Null indicates there is no mob prototype associated with
        /// this character
        /// </summary>
        public MobPrototypeData mobPrototype
        {
            get
            {
                if (VnumMobPrototype == 0) return null;
                if (mobPrototypeInternal == null)
                {
                    if (EmlenMud.WorldTemplates.AllMobPrototypes.ContainsKey(VnumMobPrototype) == false)
                    {
                        EmlenMud.LogError("Mob prototype vnum " + VnumMobPrototype.ToString() + " not found in Mob Prototype list.", null, LogType.WorldError);
                        return null;
                    }
                    mobPrototypeInternal = EmlenMud.WorldTemplates.AllMobPrototypes[VnumMobPrototype];
                }
                return mobPrototypeInternal;
            }
            set
            {
                if (!IsPlayer)
                {
                    mobPrototypeInternal = (MobPrototypeData)value;
                    VnumMobPrototype = value.Vnum;
                }
            }
        }

        public bool GetPlayerSetting(PlayerSettings setting)
        {
            if (IsPlayer)
            {
                return pcdata.SettingIsOn(setting);
            }
            return false;
        }

        public void SetPlayerSetting(PlayerSettings setting, bool fOn)
        {
            if (IsPlayer)
            {
                if (fOn) pcdata.Settings |= setting;
                else pcdata.Settings &= (~setting);
            }
        }

        public bool GetCombatOption(CombatSettings setting)
        {
            return IsFightOptionSet(setting);
        }

        public void SetCombatOption(CombatSettings setting, bool fOn)
        {
            if (fOn) cmbatOptions |= setting;
            else cmbatOptions &= (~setting);
        }
        /// <summary>
        /// Gets or sets settings...
        /// </summary>
        public bool AutoExit
        {
            get { return GetPlayerSetting(PlayerSettings.AUTOEXIT); }
            set { SetPlayerSetting(PlayerSettings.AUTOEXIT, value); }
        }

        public bool SettingAssist
        {
            get { return GetPlayerSetting(PlayerSettings.ASSIST); }
            set { SetPlayerSetting(PlayerSettings.ASSIST, value); }
        }

        /// <summary>
        /// Gets or sets the WizInvis level
        /// </summary>
        public int WizInvisLevel
        {
            get
            {
                if (IsPlayer)
                {
                    return pcdata.Wizinvis;
                }
                return 0;
            }
            set
            {
                if (IsPlayer)
                {
                    if (Level >= MiscConstants.LEVEL_PLAYER_IMMORTAL)
                    {
                        pcdata.Wizinvis = (value > Level) ? Level : value;
                    }
                }
            }
        }

        public bool this[Implants implant]
        {
            get
            {
                if (IsPlayer) { return ((PlayerData)pcdata)[implant]; }
                return false;
            }
        }

        public bool HolyWalk
        {
            get
            {
                if (IsPlayer) return ((PlayerData)pcdata).HasSpecialBits(PlayerSpecialBits.HOLYWALK);
                return false;
            }

            set
            {
                if (IsPlayer)
                {
                    if (Level >= MiscConstants.LEVEL_PLAYER_IMMORTAL)
                    {
                        if (value == false) pcdata.Specialbits &= (~PlayerSpecialBits.HOLYWALK);
                        else pcdata.Specialbits |= PlayerSpecialBits.HOLYWALK;
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the HolyLight setting (can see all, no matter what)
        /// </summary>
        public bool HolyLight
        {
            get
            {
                if (IsPlayer)
                {
                    return ((PlayerData)pcdata).HasSpecialBits(PlayerSpecialBits.HOLYLIGHT);
                }
                return false;
            }
            set
            {
                if (IsPlayer)
                {
                    if (Level >= MiscConstants.LEVEL_PLAYER_IMMORTAL)
                    {
                        if (value == false) pcdata.Specialbits &= (~PlayerSpecialBits.HOLYLIGHT);
                        else pcdata.Specialbits |= PlayerSpecialBits.HOLYLIGHT;
                    }
                }
            }
        }

        /// <summary>
        /// Returns how a certain direction appears to a character
        /// Usually used for scanning or 'look direction'
        /// </summary>
        /// <param name="currentRoom">The currentRoom to look in (doesn't assume the current character's currentRoom)</param>
        /// <param name="moveDirection">The direction</param>
        /// <returns></returns>
        public StringBuilder LookDirection(RoomData room, GeneralDirection dir)
        {
            StringBuilder sb = new StringBuilder(512);
            if (!CanSee(room)) { return room.GetReasonWhyCharacterCantSeeInRoom(this); }
            ExitData exitd = room[dir];
            if (exitd == null)
            {
                sb.Append("You see nothing in that direction.");
                return sb;
            }
            DoorData door = (DoorData)exitd.D_info;
            if (door == null)
            {
                sb.Append("It appears you can move in that direction.");
                return sb;
            }
            if (CanSee(door) == false)
            {
                sb.Append("You see nothing in that direction.");
                return sb;
            }
            if (door.IsDoor == false)
            {
                sb.Append("It appears you can move in that direction.");
                return sb;
            }
            sb.AppendLine("You see a " + door.DoorName + ".");
            if (!string.IsNullOrEmpty(door.Description)) sb.Append("\n\r" + door.Description);
            sb.AppendLine("The " + door.DoorName + " is " + door.StatusString() + ".");
            return sb;
        }

        public int ImmortalLevel
        {
            get
            {
                if (!IsPlayer) return -1;
                return (Level < MiscConstants.LEVEL_PLAYER_IMMORTAL) ? -1 : Level;
            }
        }
        /// <summary>
        /// Character must be able to see in the room first.
        /// Check with CanSee(room)
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public string GetShortExitNameInDirection(RoomData room, GeneralDirection dir)
        {
            StringBuilder sb = new StringBuilder(512);
            ExitData exitd = room[dir];
            if (exitd == null) return "";
            if (CanSee(exitd) == false) return "";
            string szAdd = "";
            string szDirLetter = StaticHelpers.DirFirstLetterCap(dir);
            if (HolyLight)
            {
                if (exitd.Vnum > 0 && exitd.to_room == null)
                {
                    szAdd = "(To missing vnum " + exitd.Vnum.ToString() + ")";
                }
                else
                {
                    ExitData exitLeadingIn = (ExitData)exitd.GetIncomingExitDataForDirection(dir);
                    if (exitLeadingIn == null)
                    {
                        szAdd = "(One-way exit)";
                    }
                    else
                    {
                        if (exitLeadingIn.Vnum != room.VnumRoom)
                        {
                            if (exitLeadingIn.to_room == null)
                            {
                                szAdd = "(Reverse exits links to missing vnum " + exitLeadingIn.Vnum.ToString() + ")";
                            }
                            else
                            {
                                szAdd = "(Reverse exits links to vnum " + exitLeadingIn.Vnum.ToString() + ")";
                            }
                        }
                    }
                }
            }
            DoorData door = (DoorData)exitd.D_info;
            if (door == null)
            {
                return szDirLetter + szAdd;
            }
            else if (CanSee(door) == false)
            {
                return szAdd;
            }
            else if (door.IsDoor)
            {
                return szDirLetter + "(" + door.DoorName + ", " + door.StatusString() + ")" +
                  szAdd;
            }
            else
            {
                return szDirLetter + szAdd;
            }
        }

        public string GetItalicsString(string sz)
        {
#if NO_SILVERLIGHT
            if (descriptor == null) return sz;
            if (descriptor.UsingInterface == InterfaceType.HTML)
            {
                return "<i>" + sz + "</i>";
            }
            else
            {
                return sz;
            }
#else
            return sz;
#endif
        }

        /// <summary>
        /// Character must be able to see in the room first.
        /// Check with CanSee(room)
        /// </summary>
        /// <param name="dir"></param>
        /// <returns></returns>
        public string GetShortExitNameInDirection(GeneralDirection dir)
        {
            RoomData room = (RoomData)EmlenMud.GetInRoom(this);
            if (room == null) return "";
            return GetShortExitNameInDirection(room, dir);
        }

        public int RemortTimes
        {
            get { if (IsPlayer) return pcdata.NRemortTimes; else return 0; }
        }

        public int CurrentStat(StatTypes stattype)
        {
            if (IsPlayer) return ((Stats)(((PlayerData)pcdata).TemporaryStats1))[stattype];
            else
            {
                // TODO for mobs
                return 15;
            }
        }

        public bool GetHasImplant(Implants implantType)
        {
            if (IsPlayer) return ((pcdata.Implants_1 & implantType) != 0);
            return false;
        }

        public bool IsAwake
        {
            get { return ((int)position > (int)CharPosition.sleeping); }
            // TODO: set
        }

        public int GuildMembershipLevel(string szGuildName)
        {
            GuildData guild = (GuildData)EmlenMud.WorldTemplates.AllGuilds[szGuildName];
            if (guild == null) return 0;
            return guild.MembershipLevel(ShortName);
        }

        public bool MemberOfGuild(string szGuildName)
        {
            return (GuildMembershipLevel(szGuildName) > 0);
        }

        public bool LeavesTracks(RoomData room)
        {
            if (HolyWalk) return false;
            if (Flying) return false;
            if (room.IsRoomFlagSet(RoomFlags.UNTRACKABLE)) return false;
            return true;
        }

        public bool Immortal
        {
            get
            {
                if (IsPlayer)
                {
                    if (Level >= MiscConstants.LEVEL_PLAYER_IMMORTAL) { return true; }
                }
                return false;
            }
        }

        public bool IsUsingInterface(InterfaceType interfaceType)
        {
            return ((usingInterface & interfaceType) != 0);
        }

        #region "String and text related"
        public string Him_Her_It
        {
            get
            {
                return (sex == Sex.FEMALE) ? "her" :
                  ((sex == Sex.MALE) ? "him" : "it");
            }
        }

        public string He_She_It
        {
            get
            {
                return (sex == Sex.FEMALE) ? "she" :
                  ((sex == Sex.MALE) ? "he" : "it");
            }
        }

        public string His_Hers_Its
        {
            get
            {
                return (sex == Sex.FEMALE) ? "hers" :
                  ((sex == Sex.MALE) ? "his" : "its");
            }
        }

        public string His_Her_Their
        {
            get
            {
                return (sex == Sex.FEMALE) ? "her" :
                  ((sex == Sex.MALE) ? "his" : "their");
            }
        }

        public string His_Hers_Theirs
        {
            get
            {
                return (sex == Sex.FEMALE) ? "hers" :
                  ((sex == Sex.MALE) ? "his" : "theirs");
            }
        }
        #endregion

        public InterfaceType usingInterface
        {
            get
            {
#if NO_SILVERLIGHT
                if (descriptor == null) return InterfaceType.HTML;
                return descriptor.UsingInterface;
#else
                return InterfaceType.HTML;
#endif
            }
            set
            {
#if NO_SILVERLIGHT
                if (descriptor == null) return;
                descriptor.UsingInterface = value;
#endif
            }
        }


        public bool HolyPeace
        {
            get
            {
                if (IsPlayer) return ((PlayerData)pcdata).HasSpecialBits(PlayerSpecialBits.HOLYPEACE);
                return false;
            }
            set
            {
                if (IsPlayer)
                {
                    if (Level >= MiscConstants.LEVEL_PLAYER_IMMORTAL)
                    {
                        if (value == false) ((PlayerData)pcdata).Specialbits &= (~PlayerSpecialBits.HOLYPEACE);
                        else ((PlayerData)pcdata).Specialbits |= PlayerSpecialBits.HOLYPEACE;
                    }
                }
            }
        }

        public List<CharacterData> WhoIsCurrentlyAttackingThisCharacter
        {
            get
            {
                List<CharacterData> rgAttackers = new List<CharacterData>(0);
                if (EmlenMud.GetInRoom(this) == null || HolyPeace) return rgAttackers;
                // Todo: do we want to check adjacent rooms / introduct projectiles?
                for (int i = 0; i < InRoomInternal.characters.Count; i++)
                {
                    CharacterData chrAttacker = InRoomInternal.characters[i];
                    if (chrAttacker.HolyPeace) return new List<CharacterData>(0);
                    if (!chrAttacker.CanSee(this)) continue;
                    if (chrAttacker.AttackingCharacter == this) rgAttackers.Add(chrAttacker);
                }
                return rgAttackers;
            }
        }

        public List<CharacterData> GetAssisters(RoomData room)
        {
            List<CharacterData> rgAssisters = new List<CharacterData>(0);
            if (AttackingCharacter == null) return rgAssisters;
            if (room == null) return rgAssisters;
            if (!room.HasCharacters) return rgAssisters;
            for (int i = 0; i < room.characters.Count; i++)
            {
                CharacterData chAssister = room.characters[i];
                if (chAssister == this) continue;
                if (!chAssister.WillAssist(this)) continue;
                if (!chAssister.CanSee(this)) continue;
                if (!chAssister.CanSee(AttackingCharacter)) continue;
                rgAssisters.Add(chAssister);
            }
            return rgAssisters;
        }

        public List<CharacterData> GetFollowers(RoomData room)
        {
            List<CharacterData> rgFollowers = new List<CharacterData>(0);
            if (room == null) return rgFollowers;
            if (!room.HasCharacters) return rgFollowers;
            for (int i = 0; i < room.characters.Count; i++)
            {
                CharacterData chrFollower = room.characters[i];
                if (chrFollower.FightInfo == null) continue;
                if (chrFollower.FightInfo.Following != this) continue;
                if (!chrFollower.CanSee(this)) continue;
                rgFollowers.Add(chrFollower);
            }
            return rgFollowers;
        }

        public CharacterData FollowingCharacter
        {
            get
            {
                if (FightInfoInternal == null) return null;
                return FightInfoInternal.Following;
            }
            set
            {
                if (this == value || value == null)
                {
                    EmlenMud.SetFollowing(FightInfo, this, null);
                }

                if (!CanSee(value)) return;

                EmlenMud.SetFollowing(FightInfo, this, value);
            }
        }

        public bool IsHolypeaceOnInRoom()
        {
            if (HolyPeace) return true;
            if (EmlenMud.GetInRoom(this) == null) return false;
            for (int i = 0; i < InRoomInternal.characters.Count; i++)
            {
                CharacterData chrAttacker = InRoomInternal.characters[i];
                if (chrAttacker.HolyPeace) return true;
            }
            return false;
        }

        public bool CanAttackChar(CharacterData chTarget)
        {
            if (EmlenMud.GetInRoom(this) != EmlenMud.GetInRoom(chTarget)) return false;
            if (IsHolypeaceOnInRoom()) return false;
            if (!CanSee(chTarget)) return false;
            // hmmm... allow CharactersInRoom to attack themselves?
            if (chTarget == this) return false;
            if (position < CharPosition.fighting) return false;

            // sure, why not... (for now)....
            return true;
        }

        public string ReasonCantAttackChar(CharacterData chTarget)
        {
            if (IsHolypeaceOnInRoom()) return "No fighting is allowed in this room right now.";
            if (!CanSee(chTarget)) return "You can't see who or what you're trying to attack!";
            if (chTarget == this) return "You can't attack yourself (for now...)";
            if (position < CharPosition.fighting) return "You must be standing to attack (for now...)";
            // TODO....
            return "";
        }

        /// <summary>
        /// returns if this character will assist chOther.  
        /// </summary>
        /// <param name="chOther"></param>
        /// <returns></returns>
        public bool WillAssist(CharacterData chOther)
        {
            // Cannot assist if you are currently attacking another creature (switch?)
            if (AttackingCharacter != null) return false;
            if (!WouldAssist(chOther)) return false;
            return true;
        }

        /// <summary>
        /// Would the character assist chOther if possible?  This might be the
        /// case if players are grouped (Master), or just have the same Master
        /// This does not consider if you are already fighting, etc
        /// </summary>
        /// <param name="chOther"></param>
        /// <returns></returns>
        public bool WouldAssist(CharacterData chOther)
        {
            // Cannot assist against the person you are attacking, or yourself
            if (AttackingCharacter == chOther) return false;
            if (this == chOther) return false;
            if (chOther.AttackingCharacter == null) return false;
            if (!CanAttackChar(chOther.AttackingCharacter)) return false;
            // No way, this character is attacking your master!
            if (chOther.AttackingCharacter == Master) return false;
            if (Master == chOther && chOther.AttackingCharacter != null &&
              InSameRoomAs(chOther) != null && InSameRoomAs(chOther.AttackingCharacter) != null)
                return true;
            if (chOther.Master == Master && chOther.AttackingCharacter != null &&
              InSameRoomAs(chOther) != null && InSameRoomAs(chOther.AttackingCharacter) != null)
                return true;
            return false;
        }

        public CharacterData Master
        {
            get
            {
                if (FightInfoInternal == null) return null;
                return FightInfo.Master;
            }
            set
            {
                if (value == null && FightInfoInternal == null) return;

                if (value != null && Master != value)
                {
                    // Perhaps stop helping the old master here...? display a message?
                    FightInfo.Master = null;
                }

                // No fighting/attacking yet... wait until the next combat round
                if (value != null) FightInfo.Master = value;
            }
        }

        public CharacterData AttackingCharacter
        {
            get
            {
                if (FightInfoInternal == null) return null;
                if (FightInfoInternal.AttackingCharacters == null) return null;
                return FightInfoInternal.AttackingCharacters;
            }
            set
            {
                if (value == null)
                {
                    if (FightInfoInternal == null) return;
                    FightInfoInternal.AttackingCharacters = null;
                    if (position == CharPosition.fighting || position == CharPosition.groundfighting)
                    {
                        position = CharPosition.standing;
                    }
                    if (EmlenMud.DynamicWorld.AllCharactersInCombatByUniqueID1.ContainsKey(AssociatedID))
                    {
                        EmlenMud.DynamicWorld.AllCharactersInCombat1.Remove(this);
                        EmlenMud.DynamicWorld.AllCharactersInCombatByUniqueID1.Remove(AssociatedID);
                    }
                    return;
                }
                if (CanAttackChar(value))
                {
                    if (FightInfoInternal == null) fightInfoInternal = new FightData();
                    FightInfoInternal.AttackingCharacters = value;
                    if (position != CharPosition.groundfighting) position = CharPosition.fighting;
                    if (!EmlenMud.DynamicWorld.AllCharactersInCombatByUniqueID1.ContainsKey(AssociatedID))
                    {
                        EmlenMud.DynamicWorld.AllCharactersInCombat1.Add(this);
                        EmlenMud.DynamicWorld.AllCharactersInCombatByUniqueID1.Add(AssociatedID, this);
                    }
                }
            }
        }

        public void EnqueueMovementCommand(string szDir)
        {
            if (rgMovementCommands == null) rgMovementCommands = new Queue<string>(4);
            rgMovementCommands.Enqueue(szDir);
        }

        public DateTime DelayedUntil
        {
            get { return CannotPerformNextActionUntil; }
            set { CannotPerformNextActionUntil = value; }
        }

        public bool IsDelayed
        {
            get
            {
                if (CannotPerformNextActionUntil >= EmlenMud.DynamicWorld.CurrentTime.dt) return true;
                if (IsFighting && FightInfo.IsDelayed) return true;
                return false;
            }
            set
            {
                if (value == false)
                {
                    CannotPerformNextActionUntil = DateTime.MinValue;
                    if (IsFighting) FightInfo.IsDelayed = false;
                }
            }
        }

        public void AddDelayMilliseconds(double msDelay)
        {
            if (CannotPerformNextActionUntil == DateTime.MinValue)
                CannotPerformNextActionUntil = EmlenMud.DynamicWorld.CurrentTime.dt;

            CannotPerformNextActionUntil.AddMilliseconds(msDelay);
        }

        public int DoFollowersAttack()
        {
            int nNewAssisters = 0;
            // TODO: test thoroughly ... no recursive loops wanted here
            List<CharacterData> rgAssisters = GetAssisters(EmlenMud.GetInRoom(this));
            for (int i = 0; i < rgAssisters.Count; i++)
            {
                CharacterData chAssister = (CharacterData)rgAssisters[i];
                // That is mean.. you are attacking someone who would assist you.... :)
                if (chAssister == AttackingCharacter)
                {
                    // Master attacks you, you no longer assist the char....
                    if (chAssister.Master == this) chAssister.Master = null;
                    continue;
                }
                // Can't see who the person you would help is fighting...
                if (!chAssister.CanSee(AttackingCharacter)) continue;
                if (chAssister.CanAttackChar(AttackingCharacter) == false) continue; // not allowed to attack
                // Only set to attack if the assister is not already fighting
                if (chAssister.AttackingCharacter == null) chAssister.AttackingCharacter = AttackingCharacter;
                nNewAssisters++;
            }
            return nNewAssisters;
        }


        #region "MinimumLevelToViewTopic-Gain Related Functions"
        /// <summary>
        /// Gain levels
        /// </summary>
        /// <param name="how_many">how many levels to gain</param>
        public void GainLevel(int how_many)
        {
            if (IsMob) MobGainLevel(how_many);
            else if (pcdata.NRemortTimes > 0) RemortPlayerGainLevel(how_many);
            else PlayerGainLevel(how_many);

            if (IsMob || EmlenMud.WorldTemplates.pow.RestoreWhenLevel == true)
            {
                RestoreHP();
                RestoreMP();
            }
        }

        public void SetMobExperience()
        {
            if (!IsMob) return;
            Experience = GetMobXP();
        }
        #endregion



        #region "HitPointsMovementPoints"

        /// <summary>
        /// For initial calculation of mob and player(?) movement points
        /// </summary>
        /// <returns></returns>
        public int CalculateInitialMP()
        {
            int init_mp = 1;
            if (mobPrototype != null)
            {
                init_mp = (EmlenMud.WorldTemplates.pow.InitialMV[0] * 2) / 3;	// Take into account mobs are usually a higher level
            }
            else if (pcdata != null)
            {
                if (pcdata.NRemortTimes > 0)
                {
                    init_mp = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.RemortMV[0], EmlenMud.WorldTemplates.pow.RemortMV[1]);
                }
                else
                {
                    init_mp = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.InitialMV[0], EmlenMud.WorldTemplates.pow.InitialMV[1]);
                }
            }
            return init_mp;
        }

        /// <summary>
        /// For initial calculation of mob and player(?) hit points
        /// </summary>
        /// <returns></returns>
        public int CalculateInitialHP()
        {
            int init_hp = 1;
            if (mobPrototype != null)
            {
                init_hp = EmlenMud.WorldTemplates.pow.InitialHp[0] / 2; // Take into account mobs are usually a higher level
            }
            else if (pcdata != null)
            {
                if (pcdata.NRemortTimes > 0)
                {
                    init_hp = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.RemortHP[0], EmlenMud.WorldTemplates.pow.RemortHP[1]);
                }
                else
                {
                    init_hp = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.InitialHp[0], EmlenMud.WorldTemplates.pow.InitialHp[1]);
                }
            }
            return init_hp;
        }

        /// <summary>
        /// Add hit points (heal), with a flag to allow HP to exceed the max
        /// </summary>
        /// <param name="n"></param>
        /// <param name="fAllowHPToExceedMaximum"></param>
        public void AddHP(int n, bool fAllowHPToExceedMaximum)
        {
            HPCurrent += n;
            if (fAllowHPToExceedMaximum == false && HPCurrent > HPMax) HPCurrent = HPMax;
            if (IS_JAVA) { java_hits(); }
        }

        /// <summary>
        /// Add movement points, with a flag to allow MP to exceed the max
        /// </summary>
        /// <param name="n"></param>
        /// <param name="fAllowMPToExceedMaximum"></param>
        public void AddMP(int n, bool fAllowMPToExceedMaximum)
        {
            MPCurrent += n;
            if (fAllowMPToExceedMaximum == false && MPCurrent > MPMax) MPCurrent = MPMax;
            if (IS_JAVA) { java_moves(); }
        }

        /// <summary>
        /// Set hit points equal to maximum
        /// </summary>
        public void RestoreHP()
        {
            HPCurrent = HPMax;
            if (IS_JAVA) { java_hits(); }
        }

        /// <summary>
        /// Set movement points equal to maximum
        /// </summary>
        public void RestoreMP()
        {
            MPCurrent = MPMax;
            if (IS_JAVA) { java_moves(); }
        }
        #endregion


        #region "Movement and Room Related"

        virtual public string ReasonIsNotAuthorizedToBeInRoom(RoomData room)
        {
            if (room.area.OpenToPlayers == 0)
            {
                if (Level < 101)
                {
                    return "You may not go to unopened areas.";
                }
            }

            if (room.area.OpenToPlayers != 0)
            {
                if (Level > 100 && pcdata.Level < 105)
                {
                    return "You are not permitted to go to an open area. " +
                      "Please stay in your zone or in another closed area. " +
                      "If you are a god, you may check out characters using the snoop command.";
                }
            }

            return "There was a problem and you were unable to go into that room.";
        }

        virtual public string GetSingularMovementDescription()
        {
            if (Flying == true) return "fly";
            switch (position)
            {
                case CharPosition.standing:
                    return "walk";
                case CharPosition.sneaking:
                    return "sneak";
                case CharPosition.running:
                    return "run";
                default:
                    return "move";
            }
        }

        virtual public string GetPluralMovementDescriptionSeenbyOthers()
        {
            if (Flying == true) return GetPluralMovementDescription() + " in from";
            switch (position)
            {
                case CharPosition.standing:
                    return GetPluralMovementDescription() + " in from";
                case CharPosition.running:
                    return GetPluralMovementDescription() + " in from";
                case CharPosition.sneaking:
                    return GetPluralMovementDescription() + " in from";
                default:
                    return "enters from";
            }
        }
        virtual public string GetPluralMovementDescription()
        {
            if (Flying == true) return "flies";
            switch (position)
            {
                default:
                    return GetSingularMovementDescription() + "s";
            }

        }


        /// <summary>
        /// Determines if the character is authorized to be in the currentRoom
        /// </summary>
        /// <param name="currentRoom">the currentRoom</param>
        /// <returns></returns>
        virtual public bool IsAuthorizedToBeInRoom(RoomData room)
        {
            if (!IsPlayer || Level >= 105) return true;
            if (room.area != null)
            {
                if (room.area.OpenToPlayers == 0 && Level < 101) return false;
                if (room.area.OpenToPlayers != 0 && Level > 100 && pcdata.Level < 105) return false;
            }
            return true;
        }

        protected bool ForceRemoveFromRoom(string szMoveMessage)
        {
            return ForceRemoveFromRoom(szMoveMessage, GeneralDirection.Max);
        }

        protected bool ForceRemoveFromRoom()
        {
            return ForceRemoveFromRoom(null, GeneralDirection.Max);
        }

        public int this[StatTypes statType]
        {
            get
            {
                return CurrentStat(statType);
            }
        }

        public bool ForceRemoveFromRoom(string szMoveMessage, GeneralDirection dirMovingTo)
        {
            if (EmlenMud.GetInRoom(this) == null) return true;

            if (dirMovingTo != GeneralDirection.Max)
            {
                EmlenMud.HandleMakingTracks(EmlenMud.GetInRoom(this), this, dirMovingTo, EnterOrLeave.leave);
            }

            // Remove the char from currentRoom on the map of others in the currentRoom
            // and show a move message
            if (((IDynamicRoomDetails)EmlenMud.GetInRoom(this).MoreRoomInfo).NumberOfPlayersInRoom > 1)
            {
                for (int n = 0; n < EmlenMud.GetInRoom(this).characters.Count; n++)
                {
                    CharacterData chr = EmlenMud.GetInRoom(this).characters[n];
                    if (this == chr) continue;
                    if (!chr.CanSee(this)) continue;
                    if (szMoveMessage != null)
                    {
                        string szBuf = EmlenMud.ShortName(chr, this);
                        if (szMoveMessage != null)
                        {
                            szBuf = szBuf + " " + szMoveMessage;
                        }
                        if (dirMovingTo != GeneralDirection.Max)
                        {
                            szBuf = szBuf + " " + dirMovingTo.ToString();
                        }
                        szBuf = szBuf + ".";
                        chr.send_to_char(szBuf);
                    }
                }
            }

            //if (!(inRoom.x == 0 && inRoom.y == 0 && inRoom.z == 0 && inRoom.VnumRoom != 1508))
            //{
            //  if (Mapping == true && MappingDisabled == false)
            //  {
            //    #region "Strange mapping stuff..."
            //    //         if ((chr.pcdata.resist_summon == -10 || chr.pcdata.resist_summon == -15))
            //    //      {
            //    //        noibm = chr.pcdata.noibm;
            //    //        kk = chr.pcdata.kk;
            //    //        mb = chr.pcdata.mb;
            //    //        dbs = chr.pcdata.dbs;
            //    //                  if (IS_JAVA(chr)) {
            //    //        if (chr.inRoom.MoreRoomInfo.linkedTo)
            //    //          display_room_mark (chr, chr.inRoom.MoreRoomInfo.linkedTo, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, 0, FALSE, FALSE);
            //    //        else
            //    //          display_room_mark (chr, chr.inRoom, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, 0, FALSE, FALSE);
            //    //                     } else {
            //    //        if (chr.inRoom.MoreRoomInfo.linkedTo)
            //    //          display_room_mark (chr, chr.inRoom.MoreRoomInfo.linkedTo, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, 0, TRUE, FALSE);
            //    //        else
            //    //          display_room_mark (chr, chr.inRoom, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, 0, TRUE, FALSE);
            //    //                    }
            //    //        if (!IS_JAVA(chr)) {
            //    //          gotoxy (chr, 1, chr.pcdata.pagelen);
            //    //          send_to_char ("\x1B[37;0m", chr);
            //    //          }
            //    //      }
            //    //       }
            //    //     for (d = descriptor_list; d != NULL; d = d.next)
            //    //       {
            //    //         x = 0;
            //    //         y = 0;
            //    //         if ((c = d.character) == NULL)
            //    //      continue;
            //    //#ifdef MAP_MOBS
            //    //         if (IS_MOB (chr) && !VIEW_MOBS (c))
            //    //      continue;
            //    //#endif
            //    //         if (!c.inRoom)
            //    //      continue;
            //    //         if (chr == c)
            //    //      continue;
            //    //         if (!can_see (c, chr) || not_is_same_align (c, chr))
            //    //      continue;
            //    //         if (!IS_SET (c.pcdata.act3, MAPPING) || IS_SET (c.pcdata.act3, DISABLED))
            //    //      continue;
            //    //   if (IS_JAVA(c)) {
            //    //         can_see_to_min_x = (XPOS (c) - 4) / 2;
            //    //         can_see_to_max_x = (24 - XPOS (c)) / 2;
            //    //         can_see_to_min_y = (YPOS (c) - 1);
            //    //         can_see_to_max_y = (8 - YPOS (c));
            //    //      } else {
            //    //         can_see_to_min_x = (XPOS (c) - 4) / 2;
            //    //              can_see_to_max_x = (20 - XPOS (c)) / 2;
            //    //         can_see_to_min_y = (YPOS (c) - 1);
            //    //              can_see_to_max_y = (7 - YPOS (c));
            //    //                 }
            //    //         if (c.inRoom.x - can_see_to_min_x > chr.inRoom.x)
            //    //      continue;
            //    //         if (c.inRoom.x + can_see_to_max_x < chr.inRoom.x)
            //    //      continue;
            //    //         if (c.inRoom.y + can_see_to_min_y < chr.inRoom.y)
            //    //      continue;
            //    //         if (c.inRoom.y - can_see_to_max_y > chr.inRoom.y)
            //    //      continue;
            //    //         if (c.inRoom.z != chr.inRoom.z ||
            //    //        c.GetInRoom() == chr.inRoom)
            //    //      continue;
            //    //         x = (chr.inRoom.x - c.inRoom.x);
            //    //         y = (c.inRoom.y - chr.inRoom.y);
            //    //         x *= 2;
            //    //         x += XPOS (c);
            //    //         y += YPOS (c);
            //    //         if (IS_JAVA(c)) {
            //    //      display_room_mark(c,chr.inRoom,x,y,1,TRUE, IS_MOB(chr));
            //    //      } else {
            //    //           sprintf (bb, "%c%c%s%s%c%c", '\x1B', '7',
            //    //             display_room_mark_direct (c, chr.inRoom, x, y, 1, TRUE, IS_MOB (chr)),
            //    //             "\x1B[37;0m",
            //    //             '\x1B', '8');
            //    //           write_to_descriptor (d.descriptor, bb, 0);
            //    //      }
            //    //         c.mobSelfDestructsAt = -5;
            //    //       }
            //    //   }
            //    //    }
            //    #endregion
            //  }
            //}

            EmlenMud.SetInRoom(this, null);
            return true;
        }


        protected bool ForceMoveToRoom(RoomData room, RoomData justCameFromRoom, string szAppearanceType)
        {
            return ForceMoveToRoom(room, justCameFromRoom, szAppearanceType, GeneralDirection.Max);
        }

        protected bool ForceMoveToRoom(RoomData room)
        {
            return ForceMoveToRoom(room, null, null, GeneralDirection.Max);
        }

        public bool ForceMoveToRoom(RoomData room, RoomData justCameFromRoom, string szAppearanceType, GeneralDirection dirCameFrom)
        {
            if (!IsAuthorizedToBeInRoom(room)) return false;
            if (room == justCameFromRoom) return false;

            if (room.Indoors && Flying)
            {
                send_to_char("You cannot fly while indoors... You land.");
                // Cmds.set_fly(this, false);
                Flying = false;	// just to make sure
            }

            if (InRoomInternal != null)
            {
                ForceRemoveFromRoom(null, GeneralDirection.Max);
            }

            EmlenMud.SetInRoom(this, room);

            if (szAppearanceType != null)
            {
                for (int i = 0; i < room.characters.Count; i++)
                {
                    CharacterData chrInRoom = room.characters[i];
                    if (chrInRoom == this) continue;
                    if (!chrInRoom.CanSee(this)) continue;
                    string szBuf = EmlenMud.ShortName(chrInRoom, this) + " " + szAppearanceType;
                    if (dirCameFrom != GeneralDirection.Max)
                    {
                        szBuf = szBuf + " " + StaticHelpers.GetDirectionMessage(dirCameFrom);
                    }
                    szBuf = szBuf + ".";
                    chrInRoom.send_to_char(szBuf);
                }
            }

            if (IsPlayer)
            {
                #region "More mapping crap"
                //    if (!IS_JAVA(chr) && IS_SET (chr.pcdata.act3, MAPPING) && IS_SET (chr.pcdata.act3, DISABLED) &&
                //   !INDOORS_MAP (chr))
                // {
                //   REMOVE_BIT (chr.pcdata.act3, MAPPING);
                //   REMOVE_BIT (chr.pcdata.act3, DISABLED);
                //   do_drawmort (chr, "");
                // }
                //    else if (!IS_JAVA(chr) && IS_SET (chr.pcdata.act3, MAPPING) && !IS_SET (chr.pcdata.act3, DISABLED) &&
                // INDOORS_MAP (chr) /*IS_SET(chr.inRoom.rmflags,INDOORS) */ )
                // {
                //   SET_BIT (chr.pcdata.act3, DISABLED);
                //   do_clear (chr, "");
                //   SET_BIT (chr.pcdata.act3, MAPPING);
                // }
                #endregion
            }


            #region "Battleground stuff"
            //if (oneroom.vnumClan >= BATTLEGROUND_START_VNUM && oneroom.vnumClan <= BATTLEGROUND_END_VNUM)
            //  {
            //    check_fgt (chr);
            //    chr.fightInfoInternal.in_battle = TRUE;
            //  }
            //else
            //  {
            //    if (chr.fightInfoInternal)
            // {
            //   chr.fightInfoInternal.in_battle = FALSE;
            //   chr.fightInfoInternal.wasroomtwo = oneroom.vnumClan;
            // }
            //  }
            #endregion

            #region "Walkthrough creation"
            if (IsPlayer)
            {
                EmlenMud.HandleWalkthroughCreation(this, (PlayerData)this.pcdata, room);
            }
            #endregion

            #region "Another TODO: something with cursed objects"
            //for (obj = chr.carryingObjects; obj != NULL; obj = obj.next_content)
            //  {
            //    if (obj.wear_loc != WEAR_NONE && obj.mobPrototype.values_2[8] > 0 &&
            //   IS_PLAYER (chr) && !FIGHTING (chr) && chr.position == STANDING &&
            //   RandIntBetween (1, 1000) < obj.mobPrototype.values_2[8] &&
            //   chr.inRoom && chr.inRoom.MoreRoomInfo)
            // {
            //   CharacterData ir;
            //   for (ir = chr.inRoom.MoreRoomInfo.CharactersInRoom; ir != NULL; ir = ir.next_in_room)
            //     {
            //       if (IS_MOB (ir))
            //    {
            //      send_to_char ("You feel an evil energy surging through you, compelling you to go wild!\n\r", chr);
            //      do_kill (chr, ir.mobPrototype.Name);
            //      goto yy;
            //    }
            //     }
            // yy:
            //    if (chr) {};
            // }
            #endregion

            #region "Unported Java and mapping code"
            //if (chr.inRoom.MoreRoomInfo.NumberOfPlayersInRoom>0) {
            //   CharacterData t;
            //   for (t=chr.inRoom.MoreRoomInfo.CharactersInRoom; t; t=t.next_in_room) {
            //      if (t==chr) continue;
            //      if (IS_JAVA(t)) {
            //         java_add_mob_window(t,chr);
            //         }
            //      }
            //   }
            //  if (IS_PLAYER (chr))
            //    {
            //      char bb[STD_LENGTH];
            //      if (!(chr.inRoom && chr.inRoom.x == 0 && chr.inRoom.y == 0 && chr.inRoom.z == 0 &&
            //       chr.inRoom.vnumClan != 1508))
            //   {
            //     if (IS_SET (chr.pcdata.act3, MAPPING) && !IS_SET (chr.pcdata.act3, DISABLED))
            //       {
            //         if (chr.pcdata.resist_summon == -10 || chr.pcdata.resist_summon == -15)
            //      {
            //                if (IS_JAVA(chr)) {
            //        if (chr.inRoom.MoreRoomInfo.linkedTo)
            //          display_room_mark (chr, chr.inRoom.MoreRoomInfo.linkedTo, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, -1, FALSE, FALSE);
            //        else
            //          display_room_mark (chr, chr.inRoom, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, -1, FALSE, FALSE);
            //                } else {
            //        if (chr.inRoom.MoreRoomInfo.linkedTo)
            //          display_room_mark (chr, chr.inRoom.MoreRoomInfo.linkedTo, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, -1, FALSE, FALSE);
            //        else
            //          display_room_mark (chr, chr.inRoom, chr.pcdata.transport_quest % 80, chr.pcdata.transport_quest / 80, -1, FALSE, FALSE);
            //                }
            //        noibm = FALSE;
            //        kk = FALSE;
            //        mb = FALSE;
            //        dbs = FALSE;
            //      if (!IS_JAVA(chr)) {
            //        gotoxy (chr, 1, chr.pcdata.pagelen);
            //        send_to_char ("\x1B[37;0m", chr);
            //        }
            //      }

            //       }
            //     for (d = descriptor_list; d != NULL; d = d.next)
            //       {
            //         x = 0;
            //         y = 0;
            //         if ((c = d.character) == NULL)
            //      continue;
            //         if (!c.inRoom)
            //      continue;
            //         if (!can_see (c, chr) || not_is_same_align (c, chr))
            //      continue;
            //         if (!IS_SET (c.pcdata.act3, MAPPING) || IS_SET (c.pcdata.act3, DISABLED))
            //      continue;
            //   if (IS_JAVA(chr)) {
            //         can_see_to_min_x = (XPOS (c) - 4) / 2;
            //         can_see_to_max_x = (24 - XPOS (c)) / 2;
            //         can_see_to_min_y = (YPOS (c) - 1);
            //         can_see_to_max_y = (8 - YPOS (c));
            //      } else {
            //         can_see_to_min_x = (XPOS (c) - 4) / 2;
            //         can_see_to_max_x = (20 - XPOS (c)) / 2;
            //         can_see_to_min_y = (YPOS (c) - 1);
            //         can_see_to_max_y = (7 - YPOS (c));
            //      }
            //         if (c.inRoom.x - can_see_to_min_x > chr.inRoom.x)
            //      continue;
            //         if (c.inRoom.x + can_see_to_max_x < chr.inRoom.x)
            //      continue;
            //         if (c.inRoom.y + can_see_to_min_y < chr.inRoom.y)
            //      continue;
            //         if (c.inRoom.y - can_see_to_max_y > chr.inRoom.y)
            //      continue;
            //         if (c.inRoom.z != chr.inRoom.z ||
            //        c.GetInRoom() == chr.inRoom)
            //      continue;
            //         x = (chr.inRoom.x - c.inRoom.x);
            //         y = (c.inRoom.y - chr.inRoom.y);
            //         x *= 2;
            //         x += XPOS (c);
            //         y += YPOS (c);
            //         if (IS_JAVA(c)) {
            //      display_room_mark(c,chr.inRoom,x,y,1,FALSE, IS_MOB(chr));
            //      } else {
            //         sprintf (bb, "%c%c%s%s%c%c", '\x1B', '7',
            //             display_room_mark_direct (c, chr.inRoom, x, y, 1, FALSE, IS_MOB (chr)),
            //             "\x1B[37;0m",
            //             '\x1B', '8');

            //         write_to_descriptor (d.descriptor, bb, 0);
            //      }
            //         c.mobSelfDestructsAt = -5;
            //       }
            //   }
            //    }
            #endregion
            return true;
        }

        #endregion

        public bool IsAggressive
        {
            get
            {
                if (IsMob)
                {
                    return (mobPrototype.PrototypeBehaviors & ActionsAndBehavior.AGGRESSIVE) != 0;
                }
                return false;
            }
            set
            {
                if (IsMob)
                {
                    if (value == true)
                    {
                        if (!IsAggressive)
                        {
                            mobPrototype.PrototypeBehaviors |= ActionsAndBehavior.AGGRESSIVE;
                            if (InRoomInternal != null)
                            {
                                if (((IDynamicRoomDetails)InRoomInternal.MoreRoomInfo).NumberOfPlayersInRoom > 0) EmlenMud.DynamicWorld.AggressiveMobs.Add(this);
                            }
                        }
                    }
                    else if (value == false)
                    {
                        if (IsAggressive)
                        {
                            mobPrototype.PrototypeBehaviors &= (~mobPrototype.PrototypeBehaviors);
                            EmlenMud.DynamicWorld.AggressiveMobs.Remove(this);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the height of a character.  
        /// If height hasn't been set before, and you try to get a
        /// character's height, it will autoset it based on race height 
        /// range (assignment only when/if needed)
        /// </summary>
        public int height
        {
            set
            {
                heightInternal = value;
            }
            get
            {
                if (heightInternal > 0) return heightInternal;
                else
                {
                    // Assigns a height for CharactersInRoom/mobs who have not had it set yet
                    if (IsPlayer)
                    {
                        RaceData race = (RaceData)pcdata.GetRaceData();
                        if (race != null)
                        {
                            heightInternal = Rand.RandIntBetween(race.Height_min, race.Height_max);
                        }
                        else
                        {
                            //LogError("Race not found: " + pcdata.Racename, null, LogType.WorldError);
                            heightInternal = ((RaceData)EmlenMud.WorldTemplates.AllRaces[0]).Height_min;
                        }
                    }
                    else if (IsMob)
                    {
                        if (mobPrototype.Mobtype == MobTypes.HUMAN) heightInternal = Rand.RandIntBetween(53, 81);
                        else if (mobPrototype.Mobtype == MobTypes.ELF) heightInternal = Rand.RandIntBetween(58, 88);
                        else if (mobPrototype.Mobtype == MobTypes.DWARF) heightInternal = Rand.RandIntBetween(41, 66);
                        else if (mobPrototype.Mobtype == MobTypes.GNOME) heightInternal = Rand.RandIntBetween(38, 58);
                        else if (mobPrototype.Mobtype == MobTypes.GIANT) heightInternal = Rand.RandIntBetween(86, 150);
                        else if (mobPrototype.Mobtype == MobTypes.DRAGON) heightInternal = Rand.RandIntBetween(178, 408);
                        else if (mobPrototype.Mobtype == MobTypes.CANINE) heightInternal = Rand.RandIntBetween(23, 48);
                        else if (mobPrototype.Mobtype == MobTypes.RODENT) heightInternal = Rand.RandIntBetween(12, 30);
                        else if (mobPrototype.Mobtype == MobTypes.INSECT) heightInternal = Rand.RandIntBetween(12, 30);
                        else if (mobPrototype.Mobtype == MobTypes.UNDEAD) heightInternal = Rand.RandIntBetween(47, 89);
                        else if (mobPrototype.Mobtype == MobTypes.GOLEM) heightInternal = Rand.RandIntBetween(77, 145);
                        else if (mobPrototype.Mobtype == MobTypes.DEMON) heightInternal = Rand.RandIntBetween(60, 95);
                        else if (mobPrototype.Mobtype == MobTypes.TROLL) heightInternal = Rand.RandIntBetween(65, 120);
                        else if (mobPrototype.Mobtype == MobTypes.BIRD) heightInternal = Rand.RandIntBetween(20, 40);
                        else if (mobPrototype.Mobtype == MobTypes.FISH) heightInternal = Rand.RandIntBetween(12, 38);
                        else if (mobPrototype.Mobtype == MobTypes.STATUE) heightInternal = Rand.RandIntBetween(50, 100);
                        else if (mobPrototype.Mobtype == MobTypes.FELINE) heightInternal = Rand.RandIntBetween(23, 48);
                        else if (mobPrototype.Mobtype == MobTypes.PLANT) heightInternal = Rand.RandIntBetween(60, 150);
                        else if (mobPrototype.Mobtype == MobTypes.GENERAL_ANIMAL) heightInternal = Rand.RandIntBetween(14, 35);
                        else if (mobPrototype.Mobtype == MobTypes.FAERIE) heightInternal = Rand.RandIntBetween(6, 20);
                        else if (mobPrototype.Mobtype == MobTypes.REPTILE) heightInternal = Rand.RandIntBetween(8, 30);
                        else if (mobPrototype.Mobtype == MobTypes.GHOST) heightInternal = Rand.RandIntBetween(53, 80);
                        else if (mobPrototype.Mobtype == MobTypes.OTHER) heightInternal = Rand.RandIntBetween(53, 81);
                        else if (mobPrototype.Mobtype == MobTypes.LYCAN) heightInternal = Rand.RandIntBetween(50, 80);
                        else if (mobPrototype.Mobtype == MobTypes.NIGHT) heightInternal = Rand.RandIntBetween(50, 80);
                        else if (mobPrototype.Mobtype == MobTypes.ORC) heightInternal = Rand.RandIntBetween(52, 71);
                        else if (mobPrototype.Mobtype == MobTypes.DARKELF) heightInternal = Rand.RandIntBetween(61, 88);
                        else if (mobPrototype.Mobtype == MobTypes.DUMMY) heightInternal = Rand.RandIntBetween(51, 70);
                        else if (mobPrototype.Mobtype == MobTypes.NONE) // we need to generalize this so races can be added in modules
                        {
                            RaceData race = GetRaceData();
                            if (race != null)
                            {
                                heightInternal = Rand.RandIntBetween(race.Height_min, race.Height_max);
                            }
                            else
                            {
                                heightInternal = Rand.RandIntBetween(51, 75);
                            }
                        }
                    }
                    else
                    {
                        // TODO LogError("Character not a player or a mob: " + Name, null, LogType.WorldError);
                        heightInternal = 1;
                    }
                }
                return heightInternal;
            }
        }

        /// <summary>
        /// This used to send a string of CharactersInRoom that told the
        /// objImage client to remove the character from view
        /// </summary>
        /// <param name="chrBeingRemoved"></param>
        protected void java_remove_mob_stuff(CharacterData chrBeingRemoved)
        {
            return;
        }

        /// <summary>
        /// Returns any RaceData associated with the character
        /// </summary>
        /// <returns></returns>
        public RaceData GetRaceData()
        {
            string rcname = null;
            if (IsPlayer)
            {
                return (RaceData)pcdata.GetRaceData();
            }
            else if (IsMob)
            {
                if (mobPrototype.Mobtype == MobTypes.NONE &&
                  mobPrototype.RaceName != "")
                {
                    rcname = mobPrototype.RaceName;
                }
            }
            return RaceData.GetRaceData(rcname);
        }


        #region "MinimumLevelToViewTopic and Experience related"

        internal void MobGainLevel(int how_many)
        {
            int hitgain = 0;
            int movegain = 0;
            for (int i = 0; i < how_many; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    if ((Level - i) >= EmlenMud.WorldTemplates.pow.Hitgain[j, 0] &&
                       (Level - i) <= EmlenMud.WorldTemplates.pow.Hitgain[j, 1])
                    {
                        hitgain = Rand.RandIntBetween(2, 5);
                        hitgain += Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.Hitgain[j, 3], EmlenMud.WorldTemplates.pow.Hitgain[j, 4]);
                        break;
                    }
                }
                for (int j = 0; j < 10; j++)
                {
                    if ((Level - i) >= EmlenMud.WorldTemplates.pow.Movegain[j, 0] &&
                       (Level - i) <= EmlenMud.WorldTemplates.pow.Movegain[j, 1])
                    {
                        movegain = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.Movegain[j, 2], EmlenMud.WorldTemplates.pow.Movegain[j, 3]);
                        break;
                    }
                }
                HPMax += ((hitgain * 4) / 3);
                MPMax += ((movegain * 4) / 3);
            }
        }

        /// <summary>
        /// Determines the amount of experience this mob will have
        /// </summary>
        /// <returns></returns>
        internal long GetMobXP()
        {
            /*mob.experience = (((mob.level+1) * (mob.level+2) * 1000) - (mob.level * mob.level * 1000));
            mob.experience /= 39;
            mob.experience += (mob.level<5 ? 0 : (mob.HPMax*5));
            mob.experience += (mob.level*((mob.level))*2); */
            if (!IsMob) return 0;
            long l = StaticHelpers.translate(EmlenMud.WorldTemplates.pow.MobExp, Level, this);
            if (Level < 7) l /= 2;
            if (NaturalArmor < 70) l += Level * 40;
            if (NaturalArmor < 0) l += Level * 40;
            if (NaturalArmor < -55) l += Level * 40;

            if (mobPrototype.Hpmult >= 1000)
            {
                l = (l * (mobPrototype.Hpmult / 1000)) / 10;
            }

            if (l <= 0) l = 1;
            return l;
        }


        internal void PlayerGainLevel(int how_many)
        {
            if (!IsPlayer) return;
            for (int i = 0; i < how_many; i++)
            {
                int hitgain = 0;
                int movegain = 0;
                for (int j = 0; j < 10; j++)
                {
                    if ((Level - i) >= EmlenMud.WorldTemplates.pow.Hitgain[j, 0] &&
                       (Level - i) <= EmlenMud.WorldTemplates.pow.Hitgain[j, 1])
                    {
                        int constitution = (((Stats)pcdata.PermanentStats1)[StatTypes.Constitution] > 30) ? 30 :
                          ((((Stats)pcdata.PermanentStats1)[StatTypes.Constitution] < 1) ? 1 : ((Stats)pcdata.PermanentStats1)[StatTypes.Constitution]);

                        hitgain = (EmlenMud.WorldTemplates.pow.ConApp[constitution - 1] * EmlenMud.WorldTemplates.pow.Hitgain[j, 2]) / 100;
                        hitgain += Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.Hitgain[j, 3], EmlenMud.WorldTemplates.pow.Hitgain[j, 4]);
                        break;
                    }
                }

                for (int j = 0; j < 10; j++)
                {
                    if ((Level - i) >= EmlenMud.WorldTemplates.pow.Movegain[j, 0] &&
                       (Level - i) <= EmlenMud.WorldTemplates.pow.Movegain[j, 1])
                    {
                        movegain = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.Movegain[j, 2], EmlenMud.WorldTemplates.pow.Movegain[j, 3]);
                        break;
                    }
                }

                HPMax += hitgain;
                MPMax += movegain;
                pcdata.Level++;
            }
        }

        internal void RemortPlayerGainLevel(int how_many)
        {
            if (!IsPlayer) return;
            for (int i = 0; i < how_many; i++)
            {
                int hitgain = 0;
                int movegain = 0;
                for (int j = 0; j < 10; j++)
                {
                    if ((Level - i) >= EmlenMud.WorldTemplates.pow.RemortHitgain[j, 0] &&
                       (Level - i) <= EmlenMud.WorldTemplates.pow.RemortHitgain[j, 1])
                    {
                        int constitution = (((Stats)pcdata.PermanentStats1)[StatTypes.Constitution] > 30) ? 30 :
                          ((((Stats)pcdata.PermanentStats1)[StatTypes.Constitution] < 1) ? 1 : ((Stats)pcdata.PermanentStats1)[StatTypes.Constitution]);

                        hitgain = (EmlenMud.WorldTemplates.pow.ConApp[constitution - 1] * EmlenMud.WorldTemplates.pow.RemortHitgain[j, 2]) / 100;
                        hitgain += Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.RemortHitgain[j, 3], EmlenMud.WorldTemplates.pow.RemortHitgain[j, 4]);
                        break;
                    }
                }

                for (int j = 0; j < 10; j++)
                {
                    if ((Level - i) >= EmlenMud.WorldTemplates.pow.RemortMovegain[j, 0] &&
                      (Level - i) <= EmlenMud.WorldTemplates.pow.RemortMovegain[j, 1])
                    {
                        movegain = Rand.RandIntBetween(EmlenMud.WorldTemplates.pow.RemortMovegain[j, 2], EmlenMud.WorldTemplates.pow.RemortMovegain[j, 3]);
                        break;
                    }
                }

                HPMax += hitgain;
                MPMax += movegain;
                pcdata.Level++;
            }
        }

        #endregion

        #region "Money related"
        /// <summary>
        /// Recalculates/rebalances gold and copper coins
        /// </summary>
        public void RecalcMoney()
        {
            long nMoney = Copper;
            Gold = Copper / 100;
            Copper = nMoney - (Gold * 100);
        }
        #endregion

        #region "Locating players, CharactersInRoom, and mob prototypes"

        /// <summary>
        /// Checks if a character exists in the game (must be an exact name match)
        /// </summary>
        /// <param name="cn">The exact string of the character.  
        /// Prefixes will not work for this function</param>
        /// <param name="fPlayerOnly">set to true if we're only looking for players</param>
        /// <returns></returns>
        public CharacterData CharacterExistsInGame(string cn, bool fPlayerOnly)
        {
            if (EmlenMud.DynamicWorld.AllChars1.ContainsKey(cn.ToString()) == false)
                return null;

            List<CharacterData> rg = EmlenMud.DynamicWorld.AllChars1[cn.ToString()];
            for (int i = 0; i < rg.Count; i++)
            {
                CharacterData cd = rg[i];
                if (fPlayerOnly == false || cd.IsPlayer) return cd;
            }
            return null;
        }

        /// <summary>
        /// Determines if a character exists in the game.  Matches
        /// exact names only.
        /// </summary>
        /// <param name="szName"></param>
        /// <param name="fPlayerOnly">if true, then look for players only</param>
        /// <returns></returns>
        //public CharacterData CharacterExistsInGame(string szName, bool fPlayerOnly)
        //{
        //  string cn = new string(szName);
        //  return CharacterExistsInGame(cn, fPlayerOnly);
        //}

        /// <summary>
        /// Finds a character in a currentRoom.  Takes into account if the
        /// character can see the other character, and works with
        /// name prefixes, etc. 
        /// </summary>
        /// <param name="szCharName">Character name (can be a prefix)</param>
        /// <param name="currentRoom">The currentRoom to find the character in</param>
        /// <param name="fMustBePlayer">If set to true, this function will only look for Players</param>
        /// <returns></returns>
        public CharacterData FindCharacterInRoom(string szCharName, RoomData room, bool fMustBePlayer)
        {
            if (room == null || szCharName == null) return null;
            if (szCharName.Length < 2 || room.HasCharacters == false) return null;
            for (int n = 0; n < room.characters.Count; n++)
            {
                CharacterData chr = room.characters[n];
                if (fMustBePlayer && chr.IsMob) continue;
                if (!CanSee(chr)) continue;
                if (chr.ShortName.StartsWith(szCharName, StringComparison.OrdinalIgnoreCase) == true)
                    return chr;
            }
            for (int n = 0; n < room.characters.Count; n++)
            {
                CharacterData chr = room.characters[n];
                if (fMustBePlayer && chr.IsMob) continue;
                if (!CanSee(chr)) continue;
                if (chr.ShortName.ToUpper().Contains(szCharName.ToUpper()) == true)
                    return chr;
            }
            return null;
        }

        /// <summary>
        /// Finds a character in a currentRoom by number.  Takes into account if the
        /// character can see the other character. 
        /// </summary>
        /// <param name="szCharName">Character number</param>
        /// <param name="currentRoom">The currentRoom to find the character in</param>
        /// <param name="fMustBePlayer">If set to true, this function will only look for Players</param>
        /// <returns></returns>
        public CharacterData FindCharacterInRoomByNumber(int nCharNum, RoomData room, bool fMustBePlayer)
        {
            if (room == null || nCharNum == 0) return null;
            if (room.HasCharacters == false) return null;
            int k = 0;
            for (int n = 0; n < room.characters.Count; n++)
            {
                CharacterData chr = ((IDynamicRoomDetails)room.MoreRoomInfo).CharactersInRoom[n];
                if (CanSee(chr) == false) continue;
                k++;
                if (fMustBePlayer && chr.IsMob) continue;
                if (k == nCharNum) return chr;
            }
            return null;
        }

        /// <summary>
        /// See <see cref="FindCharacterInRoom">FindCharacterInRoom</see>.
        /// This version looks in the currentRoom the character (looker) is currently in.
        /// This takes into account whether or not the
        /// calling character can see the target character.
        /// </summary>
        /// <param name="szCharName"></param>
        /// <param name="fMustBePlayer"></param>
        /// <returns></returns>
        public CharacterData FindCharacterInRoom(string szCharName, bool fMustBePlayer)
        {
            return FindCharacterInRoom(szCharName, EmlenMud.GetInRoom(this), fMustBePlayer);
        }

        public string Title
        {
            get
            {
                if (IsPlayer) return pcdata.Title == null ? "(No Title)" : pcdata.Title;
                else if (IsMob) return mobPrototype.Short_descr == null ? "(No Title)" : (StaticHelpers.FirstLetterCap(mobPrototype.Short_descr) + ".");
                else return "";
            }
            set
            {
                if (IsPlayer)
                {
                    pcdata.Title = StaticHelpers.MakeHTMLSafe(value);
                }
                else if (IsMob)
                {
                    mobPrototype.Short_descr = value;
                }
            }
        }

        public string ViewAsAppearsInRoom(CharacterData chVict)
        {
            string sz = "";
            if (chVict.position == CharPosition.standing)
            {
                if (chVict.IsMob)
                {
                    if (chVict.mobPrototype != null)
                    {
                        string shortDesc = chVict.ShortDescription;
                        if (!string.IsNullOrEmpty(shortDesc))
                        {
                            sz = "{C}" + shortDesc;
                        }
                        else
                        {
                            sz = "{C}" + EmlenMud.ShortName(this, chVict) + " is standing here.";
                        }
                    }
                }
                else
                {
                    sz = "{C}" + EmlenMud.ShortName(this, chVict) + " is standing here.";
                }
            }
            else
            {
                string szShortName = EmlenMud.ShortName(this, chVict);
                if (szShortName != null)
                {
                    if (szShortName.Length > 1)
                    {
                        if (chVict.IsMob)
                        {
                            if (char.IsLower(szShortName[0])) szShortName = StaticHelpers.FirstLetterCap(szShortName);
                        }
                    }

                    sz = "{C}" + szShortName + " is here, " + chVict.position.ToString() + ".";
                }
            }
            return sz;
        }
        /// <summary>
        /// Finds a character in the game by character name.  Prefixes
        /// are allowed.  This takes into account whether or not the
        /// calling character can see the target character.
        /// </summary>
        /// <param name="szCharName">The character name to look for</param>
        /// <param name="fMustBePlayer">If true, only players will be considered</param>
        /// <returns></returns>
        public CharacterData FindCharacterInGame(string szCharName, bool fMustBePlayer)
        {
            int nHash = StaticHelpers.FirstTwoLettersHash(szCharName);
            if (EmlenMud.DynamicWorld.AllCharsByFirstTwoLetters1.ContainsKey(nHash) == false)
                return null;
            List<CharacterData> rgChars = EmlenMud.DynamicWorld.AllCharsByFirstTwoLetters1[nHash];
            for (int n = 0; n < rgChars.Count; n++)
            {
                CharacterData chr = rgChars[n];
                if (fMustBePlayer && chr.IsMob) continue;
                if (CanSee(chr) == false) continue;
                if (chr.ShortName.StartsWith(szCharName, StringComparison.OrdinalIgnoreCase) == true)
                    return chr;
            }
            return null;
        }


        public List<CharacterData> FindInstancesInGame(string cname)
        {
            if (EmlenMud.DynamicWorld.AllChars1.ContainsKey(cname) == false)
                return null;
            return EmlenMud.DynamicWorld.AllChars1[cname];
        }

        //public List<CharacterData> FindInstancesInGame(string szName)
        //{
        //  string szstring = string.MakestringString(szName);
        //  if (DynamicWorld.AllChars1.ContainsKey(szstring) == false)
        //    return null;
        //  return DynamicWorld.AllChars1[szstring];
        //}

        public bool ExistsInPrototypes(string cname)
        {
            foreach (MobPrototype mproto in EmlenMud.WorldTemplates.AllMobPrototypes.Values)
            {
                if (mproto.ShortName == cname) return true;
            }
            return false;
        }


        //public bool ExistsInPrototypes(string szName)
        //{
        //  string cname = string.Getstring(szName);
        //  return ExistsInPrototypes(cname);
        //}
        #endregion


        #region "Skill and Spell related"
        public int TallySkillsAndSpells()
        {
            if (!IsPlayer) return 0;
            return pcdata.Learned.Count;
        }

        public int TallySkillsOrSpells(bool fSkill)
        {
            if (!IsPlayer) return 0;
            int tally = 0;
            Spell spell;
            foreach (var de in pcdata.Learned)
            {
                spell = EmlenMud.FindSpell(null, (int)de.Key);
                if (spell != null)
                {
                    if (fSkill == true && spell.Slot == 0) tally++;
                    else if (fSkill == false && spell.Slot != 0) tally++;
                }
            }
            return tally;
        }
        #endregion

        #region "Output and Display related"

        public void send_text(StringBuilder sb)
        {
#if NO_SILVERLIGHT
            if (descriptor != null)
            {
                descriptor.send_text(sb);
            }
#endif
        }

        public void send_text(string sz)
        {
#if NO_SILVERLIGHT
            if (descriptor != null)
            {
                descriptor.send_text(sz);
            }
#endif
        }

        public void send_to_char(string sz)
        {
#if NO_SILVERLIGHT
            if (descriptor != null)
            {
                descriptor.send_text(sz);
            }
#endif
        }

        public bool IsLinkless
        {
            get
            {
#if NO_SILVERLIGHT
                if (!IsPlayer) return false;
                if (descriptor == null) return true;
                try
                {
                    if (EmlenMud.hostWebEngine != null)
                    {
                        return (!EmlenMud.hostWebEngine.FindUser(descriptor.guid));
                    }
                }
                catch (Exception e) { GlobalLogger.Log(e, "Error", LogSeverity.Critical, true); }
#endif
                return false;
            }
        }

        public string GetPrompt()
        {
            // TODO: prompts, etc				
            string sz = "{G}" + Name + " {w}( {Y}" + HPCurrent.ToString() + "/" + HPMax.ToString() + "hp, {B}" +
              MPCurrent.ToString() + "/" + MPMax.ToString() + "mv{w} ) ";
            if (IsMob) return sz;
            if (IsPlayer)
            {
                return sz;
            }
            return "Not a player or a mob... uh oh> ";
        }

        public void java_moves() { }
        public void java_hits() { }
        private bool IS_JAVA = false;

        public bool IS_JAVA1
        {
            get { return IS_JAVA; }
            set { IS_JAVA = value; }
        }

        public bool Mapping
        {
            get
            {
                if (IsPlayer)
                {
                    return pcdata.SettingIsOn(PlayerSettings.MAPPING);
                }
                return false;
            }
            set
            {
                if (IsPlayer)
                {
                    if (value == false) pcdata.Settings &= (~PlayerSettings.MAPPING);
                    else pcdata.Settings |= PlayerSettings.MAPPING;
                }
            }
        }

        public bool MappingDisabled
        {
            get
            {
                if (IsPlayer)
                {
                    // TODO: Check if indoors, etc... not just check a flag?
                    return pcdata.SettingIsOn(PlayerSettings.MAPPING_DISABLED);
                }
                return false;
            }
            set
            {
                if (IsPlayer)
                {
                    if (value == false) pcdata.Settings &= (~PlayerSettings.MAPPING_DISABLED);
                    else pcdata.Settings |= PlayerSettings.MAPPING_DISABLED;
                }
            }
        }

        #endregion


        #region "Object and Inventory Related"
        public void RemoveObject(int idx)
        {
            ObjectData obj = (ObjectData)CarryingObjects[idx];
            // Remove all effectsAffectedBy here, etc...
            CarryingObjects.RemoveAt(idx);
        }
        #endregion

        #region "Death and Recall"
        public RoomData GetRecallRoom()
        {
            return EmlenMud.FindValidStartingRoom(this);
        }

        public int DoCharacterDeath()
        {
            if (IsPlayer)
            {
                EmlenMud.SendToOthersWhoCanSee(this, EmlenMud.GetInRoom(this), "|ShortName dies and vanishes into thin air (for now...)\n\r");
                pcdata.Deaths++;
                if (pcdata.Deaths == 1)
                {
                    send_to_char("Everything goes black... and then there is a bright light.  You have died for the first time!  Congratulations, and welcome to the club.\n\r");
                }
                else
                {
                    send_to_char("Everything goes black... and then there is a bright light.  You have died again; this is death number " + pcdata.Deaths.ToString() + ".\n\r");
                }
                ForceRemoveFromRoom();
                // TODO: Remove experience, check level, award experience points, update
                // topten, kill list, etc, etc, etc

                RoomData deathRoom = GetRecallRoom();
                RestoreHP();
                RestoreMP();
                position = CharPosition.standing;
                ForceMoveToRoom(deathRoom, null, "emerges from beyond the grave");
                StringBuilder sb = deathRoom.HowRoomLooksTo(this);
                send_to_char(sb.ToString());
            }
            else if (IsMob)
            {
                EmlenMud.SendToOthersWhoCanSee(this, EmlenMud.GetInRoom(this), "|ShortName dies and vanishes into thin air (for now...)\n\r");
                // TODO: Remove experience, check level, award experience points, update
                // topten, kill list, etc, etc, etc
                ForceRemoveFromRoom();
                // Remove from all character lists                
            }
            return 0;
        }
        #endregion

        /// <summary>
        /// Saves the current character to disk
        /// </summary>
        /// <returns></returns>
        public bool SaveCharToDisk()
        {
#if NO_SILVERLIGHT
            string szFileName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.PLAYER_DIR + "\\" + ShortName.ToString();
            return SerializationHelper.SerializeObjectOut(this, szFileName, true);
#else
            return true;
#endif
        }

#if NO_SILVERLIGHT
        /// <summary>
        /// The same as <see>AddToCharListAndPlaceInGame</see> with no option to override
        /// room authorization
        /// </summary>
        /// <param name="dd"></param>
        /// <param name="room"></param>
        /// <returns></returns>
        public bool AddToCharListAndPlaceInGame(IDescriptorData dd, RoomData room)
        {
            return AddToCharListAndPlaceInGame(dd, room, false);
        }

        /// <summary>
        /// This is the main function to call whenever a new mob is created
        /// and you want to place it into the game, or when a player logs
        /// in and needs to be placed into the game.  All objects are 
        /// registered, the character/player is added to the list, and
        /// all stats are updated
        /// </summary>
        /// <param name="currentRoom"></param>
        /// <param name="fOverrideRoomAuthorization"></param>
        /// <returns></returns>
        public bool AddToCharListAndPlaceInGame(IDescriptorData dd, RoomData room, bool fOverrideRoomAuthorization)
        {
            if (fOverrideRoomAuthorization == false &&
              IsAuthorizedToBeInRoom(room) == false) return false;

            List<CharacterData> rg = null;
            List<CharacterData> rg2 = null;

            if (EmlenMud.DynamicWorld.AllCharsByFirstTwoLetters1.ContainsKey(StaticHelpers.FirstTwoLettersHash(ShortName)) == false)
            {
                rg2 = new List<CharacterData>(8);
                EmlenMud.DynamicWorld.AllCharsByFirstTwoLetters1.Add(StaticHelpers.FirstTwoLettersHash(ShortName), rg2);
            }
            else
            {
                rg2 = EmlenMud.DynamicWorld.AllCharsByFirstTwoLetters1[StaticHelpers.FirstTwoLettersHash(ShortName)];
            }

            if (EmlenMud.DynamicWorld.AllChars1.ContainsKey(ShortName) == false)
            {
                rg = new List<CharacterData>(8);
                EmlenMud.DynamicWorld.AllChars1.Add(ShortName, rg);
            }
            else
            {
                rg = EmlenMud.DynamicWorld.AllChars1[ShortName];
            }

            if (IsMob)
            {
                // Check if there are too many mobs in the world of this prototype vnumClan
                if (!EmlenMud.DynamicWorld.WorldStats.Mobinstancecount.ContainsKey(mobPrototype.Vnum))
                    EmlenMud.DynamicWorld.WorldStats.Mobinstancecount[mobPrototype.Vnum] = (int)0;

                int nMobsOfThisType = (int)EmlenMud.DynamicWorld.WorldStats.Mobinstancecount[mobPrototype.Vnum];
                if (nMobsOfThisType >= mobPrototype.MaxInWorld) return false;

                EmlenMud.DynamicWorld.WorldStats.Mobinstancecount[mobPrototype.Vnum] = ((int)EmlenMud.DynamicWorld.WorldStats.Mobinstancecount[mobPrototype.Vnum]) + 1;
                rg.Add(this);
                rg2.Add(this);
                // Place into the currentRoom here
                if (ForceMoveToRoom(room, null, "appears in the room", GeneralDirection.Max) == false)
                {
                    rg.Remove(this);
                    rg2.Remove(this);
                    EmlenMud.DynamicWorld.WorldStats.Mobinstancecount[mobPrototype.Vnum] = ((int)EmlenMud.DynamicWorld.WorldStats.Mobinstancecount[mobPrototype.Vnum]) - 1;
                    EmlenMud.LogError("Failed to place Mob " + mobPrototype.Vnum.ToString() + " (" + ShortName.ToString() + ") into room " + room.VnumRoom.ToString() + " (" + room.Name.ToString() + " in area " + room.Areastring.ToString(), null, LogType.Always);
                    return false;
                }
                EmlenMud.DynamicWorld.WorldStats.Mobcount++;
                return true;
            }
            else if (IsPlayer)
            {
                CharacterData chr = CharacterExistsInGame(ShortName, true);
                if (chr == null && dd != null)
                {
                    chr = dd.character;
                    //if (chr.EmlenMud == null) chr.AssignEmlenMud(dd.EmlenMud);

                    RoomData toRoom = EmlenMud.WorldTemplates.GetRoom(chr.vnumInRoom);
                    if (toRoom == null)
                    {
                        toRoom = EmlenMud.FindValidStartingRoom(chr);
                        if (toRoom == null) return false;
                    }
                    else if (chr.IsAuthorizedToBeInRoom(toRoom) == false)
                    {
                        chr.send_to_char(chr.ReasonIsNotAuthorizedToBeInRoom(toRoom));
                        toRoom = EmlenMud.FindValidStartingRoom(chr);
                        if (toRoom == null) return false;
                    }

                    // Player enters game... register all objects, set everything up, etc					
                    if (chr.IsPlayer)
                    {
                        //if (chr.EmlenMud == null) ((PlayerData)chr.pcdata).AssignEmlenMud(dd.EmlenMud);
                        if (chr.pcdata.Storage != null)
                        {
                            EmlenMud.RecursiveRegisterObjects(null, null, chr, chr.pcdata.Storage, null);
                        }
                    }
                    if (chr.CarryingObjects != null)
                    {
                        EmlenMud.RecursiveRegisterObjects(chr, null, null, chr.CarryingObjects, null);
                    }

                    // Register in the dynamic world
                    EmlenMud.DynamicWorld.AllPlayers1.Add(this);
                    rg.Add(this);
                    rg2.Add(this);

                    ForceMoveToRoom(toRoom, null, "enters the game", GeneralDirection.Max);

                    dd.CurrentPlayerGameState = ConnectedState.PLAYING;
                    // show them the currentRoom / perform a 'look'....
                    dd.RgCommandHistory.Clear();
                    dd.NCommandHistoryIndex = -1;
                    dd.SendClear();
                    dd.send_text(EmlenMud.GetInRoom(dd.character).HowRoomLooksTo(dd.character));
                }
                else if (dd != null)
                {
                    // Player reconnected
                    chr.descriptor = dd;
                    dd.character = chr;
                    chr.descriptor.TcpConnection = dd.TcpConnection;
                    // should be no need to force into a currentRoom... already there
                    if (EmlenMud.GetInRoom(chr) == null)
                    {
                        // uh oh, the room no longer exists?
                        RoomData toRoom = EmlenMud.FindValidStartingRoom(chr);
                        EmlenMud.LogError("Reconnecting character " + chr.Name + " could not be placed into room " + chr.vnumInRoom.ToString(), null, LogType.Always);
                        chr.ForceMoveToRoom(toRoom, null, "reconnected", GeneralDirection.Max);
                    }
                    EmlenMud.SendToOthersWhoCanSee(
                      dd.character, EmlenMud.GetInRoom(dd.character),
                      "|ShortName just reconnected!\n\r");

                    chr.send_to_char("\n\r{Y}You have reconnected!\n\r");
                    chr.descriptor.CurrentPlayerGameState = ConnectedState.PLAYING;
                    // show them the currentRoom / perform a 'look'....
                    dd.RgCommandHistory.Clear();
                    dd.NCommandHistoryIndex = -1;
                    dd.SendClear();
                    chr.send_text(EmlenMud.GetInRoom(chr).HowRoomLooksTo(chr));
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
#endif

    }

}


// OLD CODE to PORT: character-related configuration functions, etc
//   void do_beep (CharacterData  chr, string szUserArguments)
//{
//  CharacterData vict;
//  char beep_string[STD_LENGTH];
//  DEFINE_COMMAND ("beep", do_beep, POSITION_DEAD, 100, NORMAL, "This command sends a beep from one immort to a player/other immort.")

//    if ((vict = get_char_world (chr, szUserArguments)) == NULL)
//    {
//      send_to_char ("Player not found.\n\r", chr);
//      return;
//    }
//  if (IS_MOB (vict))
//    return;
//  sprintf (beep_string, "%c%c%c%c%cBeep sent from %s to %s!\n\r", 7, 7, 7, 7, 7, NAME (chr), NAME (vict));
//  send_to_char (beep_string, vict);
//  send_to_char (beep_string, chr);
//  return;
//}


//void do_channels (CharacterData  chr, string szUserArguments)
//{
//  char arg[STD_LENGTH];
//  DEFINE_COMMAND ("channels", do_channels, POSITION_DEAD, 0, NORMAL, "Allows you to toggle yell and auction channels.")

//    one_argy (szUserArguments, arg);

//  if (arg[0] == '\0')
//    {
//      if (IS_PLAYER (chr) && IS_SET (chr->currentActionsAndBehavior, PLR_SILENCE))
//   {
//     send_to_char ("You are silenced.\n\r", chr);
//     return;
//   }

//      send_to_char ("\x1B[33;1m\n\rChannels:\x1B[37;0m\n\r\n\r", chr);


//      send_to_char (!IS_SET (chr->pcdata->deaf, CHANNEL_AUCTION)
//          ? "\x1B[37;1m*\x1B[0mAUCTION  - You are listening to the auction channel.\n\r"
//        : " auction  - You are ignoring the auction channel.\n\r",
//          chr);
//      send_to_char (!IS_SET (chr->pcdata->deaf, CHANNEL_YELL)
//       ? "\x1B[37;1m*\x1B[0mYELL     - You are listening to yells.\n\r"
//          : " yell     - You are ignoring yells.\n\r",
//          chr);
//      send_to_char ("\x1B[37;0mTo turn a specific channel on/off, type the channel name alone.\n\r", chr);

//    }
//  else
//    {
//      bool fClear;
//      int bit;

//      if (arg[0] == '+')
//   fClear = TRUE;
//      else if (arg[0] == '-')
//   fClear = FALSE;
//      else
//   {
//     send_to_char ("Channels -channel or +channel?\n\r", chr);
//     return;
//   }

//      if (!str_cmp (arg + 1, "auction"))
//   bit = CHANNEL_AUCTION;
//      else if (!str_cmp (arg + 1, "yell"))
//   bit = CHANNEL_YELL;
//      else
//   {
//     send_to_char ("Set or clear which channel?\n\r", chr);
//     return;
//   }

//      if (fClear)
//   {
//     char buf[STD_LENGTH];
//     REMOVE_BIT (chr->pcdata->deaf, bit);
//     sprintf (buf, "You now are aware of %ss.\n\r", arg + 1);
//     send_to_char (buf, chr);
//   }
//      else
//   {
//     char buf[STD_LENGTH];
//     SET_BIT (chr->pcdata->deaf, bit);
//     sprintf (buf, "You now ignore %ss.\n\r", arg + 1);
//     send_to_char (buf, chr);
//   }
//    }

//  return;
//}



//void display_toggles (CharacterData  chr)
//{
//  send_to_char ("Groundfighting Options:\n\r", chr);
//  check_ced (chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_JUJI))
//    send_to_char ("\x1B[30;1m[\x1B[34mJOINTLOCK \x1B[30m]\x1B[37;1m You WILL attempt wrist-bends and arm hyperextensions.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[jointlock ] \x1B[37;0m You WON'T attempt wrist-bends and arm hyperextensions.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_CHOKE))
//    send_to_char ("\x1B[30;1m[\x1B[34m  CHOKE   \x1B[30m]\x1B[37;1m You WILL attempt to choke your victim.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[  choke   ] \x1B[37;0mYou WON'T attempt to choke your victim.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_BITE))
//    send_to_char ("\x1B[30;1m[\x1B[34m   BITE   \x1B[30m]\x1B[37;1m You WILL attempt to bite your victim.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[   bite   ] \x1B[37;0mYou WON'T attempt to bite your victim.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_ELBOW))
//    send_to_char ("\x1B[30;1m[\x1B[34m  ELBOW   \x1B[30m]\x1B[37;1m You WILL use your elbows.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[  elbow   ] \x1B[37;0mYou WON'T use your elbows.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_KNEE))
//    send_to_char ("\x1B[30;1m[\x1B[34m   KNEE   \x1B[30m]\x1B[37;1m You WILL use your knees.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[   knee   ] \x1B[37;0mYou WON'T use your knees.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_HEADBUTT))
//    send_to_char ("\x1B[30;1m[\x1B[34m HEADBUTT \x1B[30m]\x1B[37;1m You WILL headbutt.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[ headbutt ] \x1B[37;0mYou WON'T headbutt.\n\r\x1B[37;0m", chr);
//  send_to_char ("\n\rNormal Combat Options:\n\r", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_POWER))
//    send_to_char ("\x1B[30;1m[\x1B[34m  POWER   \x1B[30m]\x1B[37;1m You concentrate your efforts on power.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[  power   ] \x1B[37;0mYou concentrate your efforts on speed.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_AGGRESSIVE))
//    send_to_char ("\x1B[30;1m[\x1B[34mAGGRESSIVE\x1B[30m]\x1B[37;1m You will fight aggressively.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[aggressive] \x1B[37;0mYou will fight defensively.\n\r\x1B[37;0m", chr);
//  if (IS_SET (chr->ced->cmbatOptions, F_GROUND))
//    send_to_char ("\x1B[30;1m[\x1B[34m  GROUND  \x1B[30m]\x1B[37;1m You are indifferent to chAttacking on the ground.\n\r\x1B[0m", chr);
//  else
//    send_to_char ("\x1B[30;1m[  ground  ] \x1B[37;0mYou will try to avoid groundfighting at all costs.\x1B[37;0m\n\r", chr);
//  return;
//}

//void 
//do_fight (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("fight", do_fight, POSITION_SLEEPING, 0, NORMAL, "This command allows you to view/change your chAttacking options.")

//    check_ced (chr);
//  if (szUserArguments[0] == '\0')
//    {
//      send_to_char ("NOTE: To toggle fight options, type FIGHT <option>\n\r\n\r", chr);
//      display_toggles (chr);
//      return;
//    }
//  if (!str_cmp (szUserArguments, "jointlock"))
//    chr->ced->cmbatOptions ^= F_JUJI;
//  else if (!str_cmp (szUserArguments, "headbutt"))
//    chr->ced->cmbatOptions ^= F_HEADBUTT;
//  else if (!str_cmp (szUserArguments, "elbow"))
//    chr->ced->cmbatOptions ^= F_ELBOW;
//  else if (!str_cmp (szUserArguments, "knee"))
//    chr->ced->cmbatOptions ^= F_KNEE;
//  else if (!str_cmp (szUserArguments, "bite"))
//    chr->ced->cmbatOptions ^= F_BITE;
//  else if (!str_cmp (szUserArguments, "choke"))
//    chr->ced->cmbatOptions ^= F_CHOKE;
//  else if (!str_cmp (szUserArguments, "aggressive"))
//    chr->ced->cmbatOptions ^= F_AGGRESSIVE;
//  else if (!str_cmp (szUserArguments, "power"))
//    chr->ced->cmbatOptions ^= F_POWER;
//  else if (!str_cmp (szUserArguments, "ground"))
//    chr->ced->cmbatOptions ^= F_GROUND;
//  else
//    {
//      send_to_char ("Invalid fight option.\n\r", chr);
//      return;
//    }
//  send_to_char ("Fight option toggled.\n\r", chr);
//  return;
//}

//void do_wimpy (CharacterData  chr, string szUserArguments)
//{
//  char buf[STD_LENGTH];
//  char arg[SML_LENGTH];
//  int fleeWhenHPBelow;
//  DEFINE_COMMAND ("fleeWhenHPBelow", do_wimpy, POSITION_DEAD, 0, NORMAL, "This command allows you to change your auto-flee below <amt> hps.")

//    one_argy (szUserArguments, arg);
//  check_ced (chr);
//  if (arg[0] == '\0')
//    fleeWhenHPBelow = 20;
//  else
//    fleeWhenHPBelow = atoi (arg);
//  if (fleeWhenHPBelow < 0)
//    {
//      send_to_char ("Invalid.\n\r", chr);
//      return;
//    }
//  if (fleeWhenHPBelow > (chr->HPMax / 3))
//    {
//      send_to_char ("Your fleeWhenHPBelow must be less than 1/3 of your max hps!\n\r", chr);
//      return;
//    }
//  chr->ced->fleeWhenHPBelow = fleeWhenHPBelow;
//  sprintf (buf, "You decide to flee at \x1B[1m%d\x1B[0m HPCurrent points.\n\r", fleeWhenHPBelow);
//  send_to_char (buf, chr);
//  return;
//}

//void do_blank (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("blank", do_blank, POSITION_DEAD, 0, NORMAL, "This command toggles whether or not you have a blank line before your prompt.")
//    if (!chr)
//    return;
//  if (IS_SET (chr->pcdata->act2, PLR_BLANK))
//    do_config (chr, "-blank");
//  else
//    do_config (chr, "+blank");
//  return;
//}

//void do_brief (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("brief", do_brief, POSITION_DEAD, 0, NORMAL, "This command toggles whether or not you see long currentRoom descriptions.")
//    if (!chr)
//    return;
//  if (IS_SET (chr->pcdata->act2, PLR_BRIEF))
//    do_config (chr, "-brief");
//  else
//    do_config (chr, "+brief");
//  return;
//}


//void do_pagelen (CharacterData  chr, string szUserArguments)
//{
//  char buf[STD_LENGTH];
//  char arg[SML_LENGTH];
//  int lines;
//  DEFINE_COMMAND ("pagelength", do_pagelen, POSITION_DEAD, 0, NORMAL, "This changes your default page length/screen size.")

//    one_argy (szUserArguments, arg);
//  if (arg[0] == '\0')
//    lines = 24;
//  else
//    lines = atoi (arg);
//  if (lines < 1)
//    {
//      send_to_char (
//          "Negative or Zero values for a page pause is not legal.\n\r",
//           chr);
//      return;
//    }
//  if (lines > 100)
//    {
//      send_to_char (
//           "Can't set page length greater than 100.\n\r",
//           chr);
//      return;
//    }
//  chr->pcdata->pagelen = lines;
//  do_clear (chr, "");
//  if (!IS_SET (chr->pcdata->act2, PLR_BLANKPROMPT))
//    {
//      sprintf (buf, "Page pause set to \x1B[1m%d\x1B[0m lines.\n\r", lines);
//      send_to_char (buf, chr);
//    }
//  return;
//}

//extern string prompts[];

//void do_prompt (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("prompt", do_prompt, POSITION_DEAD, 0, NORMAL, "This command toggles your prompt on or off.")
//    if (pow.playerPrompt && !str_cmp (szUserArguments, "all"))
//    {
//      send_to_char ("Pick a default prompt by using 'prompt <letter>':\n\r", chr);
//      send_to_char ("[A] ", chr);
//      try_prompt (prompts[0], chr);
//      send_to_char ("[B] ", chr);
//      try_prompt (prompts[1], chr);
//      send_to_char ("[C] ", chr);
//      try_prompt (prompts[2], chr);
//      send_to_char ("[D] ", chr);
//      try_prompt (prompts[3], chr);
//      send_to_char ("[E] ", chr);
//      try_prompt (prompts[4], chr);
//      send_to_char ("[F] ", chr);
//      try_prompt (prompts[5], chr);
//      send_to_char ("[G] ", chr);
//      try_prompt (prompts[6], chr);
//      send_to_char ("[H] ", chr);
//      try_prompt (prompts[7], chr);
//      send_to_char ("[I] ", chr);
//      try_prompt (prompts[8], chr);
//      send_to_char ("[J] ", chr);
//      try_prompt (prompts[9], chr);
//      send_to_char ("[K] ", chr);
//      try_prompt (prompts[10], chr);
//      send_to_char ("[L] ", chr);
//      try_prompt (prompts[11], chr);
//      send_to_char ("[M] ", chr);
//      try_prompt (prompts[12], chr);
//      send_to_char ("[N] ", chr);
//      try_prompt (prompts[13], chr);
//      send_to_char ("[O] ", chr);
//      try_prompt (prompts[14], chr);
//      send_to_char ("[P] ", chr);
//      try_prompt (prompts[15], chr);
//      send_to_char ("Or make your own prompt.  (see help prompt).\n\r", chr);
//      return;
//    }
//  if (szUserArguments[0] != '\0' && szUserArguments[1] == '\0' && UPPER (szUserArguments[0]) >= 'A')
//    {
//      set_default_prompt (chr, szUserArguments[0]);
//      return;
//    }
//  if (pow.playerPrompt && szUserArguments[0] != '\0')
//    {
//      if (!check_pr (szUserArguments))
//   {
//     send_to_char ("Invalid prompt.  See help prompt for info.\n\r", chr);
//     return;
//   }
//      if (chr->pcdata->rprompt)
//   free_string (chr->pcdata->rprompt);
//      chr->pcdata->rprompt = str_dup (szUserArguments);
//      send_to_char ("Prompt set.  See help prompt for info.\n\r", chr);
//      return;
//    }
//  if (!IS_SET (chr->pcdata->act2, PLR_PROMPT))
//    {
//      send_to_char ("Prompt \x1B[1mON\x1B[0m.\n\r", chr);
//      SET_BIT (chr->pcdata->act2, PLR_PROMPT);
//    }
//  else
//    {
//      REMOVE_BIT (chr->pcdata->act2, PLR_PROMPT);
//      send_to_char ("Prompt \x1B[1;30mOFF\x1B[0m.\n\r", chr);
//    }
//  return;
//}

//void do_auto (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("auto", do_auto, POSITION_DEAD, 0, NORMAL, "See Config.")

//    do_config (chr, "");
//  return;
//}

//void do_autoloot (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("autoloot", do_autoloot, POSITION_DEAD, 0, NORMAL, "Toggles autoloot on/off.")

//    send_to_char ("AUTOLOOT ", chr);
//  do_config (chr, "autoloot");
//  return;
//}

//void do_autosac (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("autosac", do_autosac, POSITION_DEAD, 0, NORMAL, "Toggles autosacrificing on/off.")

//    send_to_char ("AUTOSAC ", chr);
//  do_config (chr, "autosac");
//  return;
//}

//void do_autoexit (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("autoexit", do_autoexit, POSITION_DEAD, 0, NORMAL, "Toggles autoexit on/off.")

//    send_to_char ("AUTOEXIT ", chr);
//  do_config (chr, "autoexit");
//  return;
//}

//void do_autogold (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("autogold", do_autogold, POSITION_DEAD, 0, NORMAL, "Toggles automatic gold looting on/off.")

//    send_to_char ("AUTOGOLD ", chr);
//  do_config (chr, "autogold");
//  return;
//}

//void do_autosplit (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("autosplit", do_autosplit, POSITION_DEAD, 0, NORMAL, "Toggles automatic gold splitting on/off.")

//    send_to_char ("AUTOSPLIT ", chr);
//  do_config (chr, "autosplit");
//  return;
//}

//void do_assist (CharacterData  chr, string szUserArguments)
//{
//  char arg[SML_LENGTH];
//  CharacterData victim;
//  DEFINE_COMMAND ("assist", do_assist, POSITION_STANDING, 0, NORMAL, "Toggles autoassist on/off or assists a specified player in combat.")

//    if (IS_PLAYER (chr) && szUserArguments[0] == '\0')
//    {
//      /* send_to_char( "ASSIST ", chr );
//         do_config( chr, "assist" ); */
//      send_to_char ("SettingAssist who?\n\r", chr);
//      return;
//    }
//  one_argy (szUserArguments, arg);
//  if ((victim = get_char_room (chr, arg)) == NULL)
//    {
//      send_to_char ("SettingAssist WHO?\n\r", chr);
//      return;
//    }
//  if (chr->position == POSITION_GROUNDFIGHTING)
//    {
//      currentActionsAndBehavior ("I don't think so! You are on the ground, chAttacking!", chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if (chr->position != POSITION_STANDING)
//    {
//      currentActionsAndBehavior ("You probably should get into a standing position first...", chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if (IS_PLAYER (chr) && IS_MOB (victim))
//    {
//      currentActionsAndBehavior ("$N doesn't want your help!", chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if (victim == chr)
//    {
//      send_to_char ("SettingAssist yourself? SettingAssist yourself!\n\r", chr);
//      return;
//    }
//  if (FIGHTING (victim) == NULL)
//    {
//      send_to_char ("To assist someone, they must be chAttacking...\n\r", chr);
//      return;
//    }
//  if (FIGHTING (victim) == chr)
//    {
//      send_to_char ("It would be foolish to assist your opponent!\n\r", chr);
//      return;
//    }
//  if (MASTER (victim) == chr && IS_PLAYER (chr))
//    {
//      if (IS_PLAYER (chr) && !IS_MOB (victim) && LEVEL (victim->fightInfoInternal->chAttacking) + 10 < LEVEL (chr))
//   {
//     send_to_char ("A strange force prevents you from assisting!\n\r", chr);
//     return;
//   }
//    }
//  currentActionsAndBehavior ("You join $N's fight!", chr, NULL, victim, TO_CHAR);
//  currentActionsAndBehavior ("$n assists you!", chr, NULL, victim, TO_VICT);
//  currentActionsAndBehavior ("$n joins in the fight, assisting $N!", chr, NULL, victim, TO_NOTVICT);
//  check_fgt (chr);
//  check_fgt (victim);
//  chr->fightInfoInternal->chAttacking = victim->fightInfoInternal->chAttacking;
//  set_fighting (chr, victim->fightInfoInternal->chAttacking);
//  return;
//}

//void do_color (CharacterData  chr, string szUserArguments)
//{
//  DEFINE_COMMAND ("color", do_ansi, POSITION_DEAD, 0, NORMAL, "Configures channel colors.")

//    return;
//}

//void do_ansi (CharacterData  chr, string szUserArguments)
//{
//  CHANNEL *cn;
//  char arg[SML_LENGTH];
//  char buf[STD_LENGTH];
//  string t;
//  int i = 0;
//  int k;
//  int p;
//  DEFINE_COMMAND ("ansi", do_ansi, POSITION_DEAD, 0, NORMAL, "Configures channel colors.")


//    szUserArguments = one_argy (szUserArguments, arg);

//  if (arg[0] == '\0')
//    {
//      if (IS_SET (chr->pcdata->act2, PLR_ANSI))
//   {
//     p = chr->position;
//     chr->position = POSITION_STANDING;
//     send_to_char ("Channel Color Configuration/Settings...", chr);
//     for (cn = chan_first; cn != NULL; cn = cn->next)
//       {
//         if (cn->level > LEVEL (chr))
//      {
//        i++;
//        continue;
//      }
//         sprintf (buf, "$R%s", chr->pcdata->chan_color[i]);
//         currentActionsAndBehavior (buf, chr, NULL, chr, TO_CHAR);
//         sprintf (buf, "%12ss \x1B[37;0mwill use color code \x1B[37;1m%s\x1B[37;0m.",
//             capitalize (cn->commands[0]),
//             chr->pcdata->chan_color[i]);
//         send_to_char (buf, chr);
//         i++;
//       }
//     send_to_char ("\n\r", chr);
//     chr->position = p;
//     return;
//   }
//      send_to_char ("To toggle ANSI, type 'config ansi'. GeneralTypeOfEffect HELP ANSI for MoreRoomInfo help.\n\r", chr);
//      return;
//    }
//  i = 0;
//  for (cn = chan_first; cn != NULL; cn = cn->next)
//    {
//      if (!str_cmp (arg, cn->commands[0]))
//   break;
//      i++;
//    }
//  if (!cn)
//    {
//      send_to_char ("I don't know of that channel.\n\r", chr);
//      return;
//    }
//  if (szUserArguments[0] == '\0')
//    {
//      send_to_char ("Change the color code to what?\n\r", chr);
//      return;
//    }
//  k = 0;
//  for (t = szUserArguments; *t != '\0'; t++)
//    {
//      if (*t != 'R' && *t != 'B' && (*t < '0' || *t > '9') && *t != '$')
//   {
//     send_to_char ("Invalid code encountered.  Use $R for regular text, not $N.\n\r", chr);
//     return;
//   }
//      k++;
//    }
//  if (k > 9)
//    {
//      send_to_char ("Color code too long!\n\r", chr);
//      return;
//    }
//  strcpy (chr->pcdata->chan_color[i], szUserArguments);
//  send_to_char ("Color set.\n\r", chr);
//  ansi_color (NTEXT, chr);
//  return;
//}

//void 
//do_config (CharacterData  chr, string szUserArguments)
//{
//  char arg[SML_LENGTH];
//  char buf[STD_LENGTH];
//  DEFINE_COMMAND ("config", do_config, POSITION_DEAD, 0, NEVER, "This allows you to configure several aspects of gameplay.")

///* if ( IS_MOB(chr) )
//   return;
// */
//    one_argy (szUserArguments, arg);
//  if (arg[0] == '\0')
//    {
//      /* send_to_char( "[ KeywordList ] Option\n\r", chr ); */
//      send_to_char ("\n\r", chr);
//      /*if ( IS_IMMORTAL(chr) )
//         {
//       */
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_PROMPT_UP)
//          ? "\x1B[37;1m[ \x1B[34mUPPROMPT \x1B[37;1m ] If you have mapping on, the prompt will be up.\n\r"
//          : "\x1B[37;0m[ \x1B[34mupprompt  \x1B[37m] If you have mapping on, the prompt will be down.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_AUTOEXIT)
//          ? "\x1B[37;1m[ \x1B[34mAUTOEXIT \x1B[37;1m ] You automatically see exits.\n\r"
//          : "\x1B[37;0m[ \x1B[34mautoexit  \x1B[37m] You don't automatically see exits.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_AUTOLOOT)
//          ? "\x1B[37;1m[ \x1B[34mAUTOLOOT  \x1B[37;1m] You automatically loot corpses.\n\r"
//          : "\x1B[37;0m[\x1B[34m autoloot  \x1B[37;0m] You don't automatically loot corpses.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_AUTOSAC)
//          ? "\x1B[37;1m[\x1B[34m AUTOSAC   \x1B[37;1m] You automatically sacrifice corpses.\n\r"
//          : "\x1B[37;0m[\x1B[34m autosac   \x1B[37;0m] You don't automatically sacrifice corpses.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_AUTOGOLD)
//          ? "\x1B[37;1m[\x1B[34m AUTOGOLD  \x1B[37;1m] You automatically loot coins from corpses.\n\r"
//          : "\x1B[37;0m[\x1B[34m autogold  \x1B[37;0m] You don't automatically loot coins from corpses.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_AUTOSPLIT)
//          ? "\x1B[37;1m[\x1B[34m AUTOSPLIT \x1B[37;1m] You automatically split coins looted from corpses.\n\r"
//          : "\x1B[37;0m[ \x1B[34mautosplit \x1B[37;0m] You don't automatically split coins looted from corpses.\n\r"
//          ,chr);
//      /*
//         }
//       */
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_ASSIST)
//          ? "\x1B[37;1m[\x1B[34m ASSIST   \x1B[37;1m ] You automatically assist your group in combat.\n\r"
//          : "\x1B[37;0m[\x1B[34m assist   \x1B[37;0m ] You don't automatically assist your group in combat.\n\r"
//          ,chr);
//      if (IS_PLAYER (chr))
//   send_to_char ((chr->pcdata->prompt == 2)
//            ? "\x1B[37;1m[\x1B[34m FLOATBOT \x1B[37;1m ] Bottom-Floating prompt is on.\n\r"
//            : "\x1B[37;0m[\x1B[34m floatbot \x1B[37;0m ] Bottom-Floating prompt is off.\n\r"
//            ,chr);
//      if (IS_PLAYER (chr))
//   send_to_char ((chr->pcdata->prompt == 1)
//            ? "\x1B[37;1m[\x1B[34m FLOATTOP \x1B[37;1m ] Top-Floating prompt is on.\n\r"
//            : "\x1B[37;0m[\x1B[34m floattop \x1B[37;0m ] Top-Floating prompt is off.\n\r"
//            ,chr);
///*
//   send_to_char( IS_SET(chr->pcdata->act2, PLR_BLANKPROMPT)
//   ? "\x1B[37;1m[\x1B[34m NOMOVE  \x1B[37;1m ] Prompt stays stationary. Pagelen and ANSI must be set.\n\r"
//   : "\x1B[37;0m[\x1B[34m nomove  \x1B[37;0m ] Prompt scrolls up with the rest of the text.\n\r"
//   , chr );
// */
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_BLANK)
//          ? "\x1B[37;1m[\x1B[34m BLANK    \x1B[37;1m ] You have a blank line before your prompt.\n\r"
//          : "\x1B[37;0m[\x1B[34m blank    \x1B[37;0m ] You have no blank line before your prompt.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_BRIEF)
//          ? "\x1B[37;1m[\x1B[34m BRIEF    \x1B[37;1m ] You see brief descriptions.\n\r"
//          : "\x1B[37;0m[\x1B[34m brief    \x1B[37;0m ] You see long descriptions.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_COMBINE)
//          ? "\x1B[37;1m[\x1B[34m COMBINE  \x1B[37;1m ] You see object lists in combined format.\n\r"
//          : "\x1B[37;0m[\x1B[34m combine  \x1B[37;0m ] You see object lists in single format.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_PROMPT)
//   ? "\x1B[37;1m[\x1B[34m PROMPT    \x1B[37;1m] You have a prompt.\n\r"
//          : "\x1B[37;0m[\x1B[34m prompt    \x1B[37;0m] You don't have a prompt.\n\r"
//          ,chr);
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_ANSI)
//          ? "\x1B[37;1m[\x1B[34m ANSI     \x1B[37;1m ] You receive ansi color codes.\n\r"
//          : "\x1B[37;0m[ \x1B[34mansi     \x1B[37;0m ] You don't receive ansi color codes.\n\r"
//          ,chr);
//      /* send_to_char( IS_SET(chr->pcdata->act2, PLR_TELNET_GA)
//         ? "\x1B[37;1m[\x1B[34m TELNETGA\x1B[37;1m ] You can not use arrow keys, echo local.\n\r"
//         : "\x1B[37;0m[\x1B[34m telnetga\x1B[37;0m ] You can use arrow keys, let mud echo.\n\r"
//         , chr ); */
//      if (IS_PLAYER (chr))
//   {
//     send_to_char (chr->pcdata->challenge_on
//         ? "\x1B[37;1m[\x1B[34m CHALLNGE  \x1B[37;1m] You allow arena challenges from other players.\n\r"
//         : "\x1B[37;0m[\x1B[34m challnge  \x1B[37;0m] You cannot be challenged in the arena.\n\r"
//         ,chr);
//     send_to_char (chr->pcdata->arena_msg == 1
//         ? "\x1B[37;1m[\x1B[34m ARENA     \x1B[37;1m] You will see updated status of arena battles.\n\r"
//         : (chr->pcdata->arena_msg == 2
//            ? "\x1B[37;1m[\x1B[34m aReNa     \x1B[37;1m] You will see battles start/stop but nothing else.\n\r"
//            : "\x1B[37;0m[\x1B[34m arena     \x1B[37;0m] You will not see any arena messages.\n\r"
//         )
//         ,chr);
//   }
//      send_to_char (IS_SET (chr->pcdata->act2, PLR_SILENCE)
//      ? "\x1B[37;1m[ \x1B[34mSILENCE\x1B[37;1m ] You are silenced.\n\r"
//          : ""
//          ,chr);
//      if (IS_IMMORTAL (chr))
//   {
//     send_to_char (IS_SET (chr->currentActionsAndBehavior, PLR_HOLYLIGHT) && IS_IMMORTAL (chr)
//         ? ""
//          : "[ holylite ] Holylight is off; please type HOLYLIGHT.\n\r"
//         ,chr);
//     send_to_char (IS_SET (chr->currentActionsAndBehavior, PLR_HOLYPEACE) && IS_IMMORTAL (chr)
//         ? "\x1B[37;1m[ \x1B[34mPEACE   \x1B[37;1m ] No mortals can fight in your presence.\x1B[37;0m\n\r"
//         : "\x1B[37;0m[ \x1B[34mpeace   \x1B[37;0m ] Your presence doesn't affect mortal battles.\n\r"
//         ,chr);
//     send_to_char (IS_SET (chr->pcdata->act2, PLR_HOLYLAG) && IS_IMMORTAL (chr)
//         ? "\x1B[37;1m[ \x1B[34mHOLYLAG \x1B[37;1m ] You are lagged (delayed) up the butt, like mortals.\x1B[37;0m\n\r"
//         : "\x1B[37;0m[ \x1B[34mholylag \x1B[37;0m ] You aren't 'delayed' on any commands.\n\r", chr);
//     send_to_char (IS_SET (chr->currentActionsAndBehavior, PLR_HOLYWALK) && IS_IMMORTAL (chr)
//         ? ""
//       : "[ holywalk ] Holywalk is off; please type HOLYWALK.\n\r"
//         ,chr);
//   }
//      send_to_char ("\n\r\x1B[32;1mPlease see the CHANNEL command also.\x1B[37;0m\n\r", chr);
//    }
//  else
//    {
//      char arg2[STD_LENGTH];
//      bool fSet;
//      int bit;
//     arg2[0]='\0';
//      fSet = arg[0] == '+';
//      if (arg[0] == '-' || arg[0] == '+')
//   {
//     sprintf (arg2, "%c", arg[0]);
//     sprintf (arg, "%s", arg + 1);
//   }
//      if (!str_cmp (arg, "peace"))
//   {
//     send_to_char ("Please type 'holypeace' at the prompt to toggle it on/off.\n\r", chr);
//     return;
//   }
//      if (!str_cmp (arg, "autoexit") /*&& IS_IMMORTAL(chr) */ )
//   bit = PLR_AUTOEXIT;
//      else if (!str_cmp (arg, "autoloot") /* && IS_IMMORTAL(chr) */ )
//   bit = PLR_AUTOLOOT;
//      else if (!str_cmp (arg, "autosac") /* && IS_IMMORTAL(chr) */ )
//   bit = PLR_AUTOSAC;
//      else if (!str_cmp (arg, "autogold") /* && IS_IMMORTAL(chr) */ )
//   bit = PLR_AUTOGOLD;
//      else if (!str_cmp (arg, "upprompt"))
//   bit = PLR_PROMPT_UP;
//      else if (!str_cmp (arg, "assist"))
//   bit = PLR_ASSIST;
//      else if (!str_cmp (arg, "autosplit"))
//   bit = PLR_AUTOSPLIT;
//      else if (!str_cmp (arg, "blank"))
//   bit = PLR_BLANK;
//      else if (!str_cmp (arg, "floatbot"))
//   {
//     if (chr->pcdata->prompt == 0)
//       {
//         chr->pcdata->prompt = 2;
//         set_it_up (chr);
//         return;
//       }
//     else
//       {
//         chr->pcdata->prompt = 0;
//         do_clear (chr, "");
//         return;
//       }
//   }
//      else if (!str_cmp (arg, "floattop"))
//   {
//     if (chr->pcdata->prompt == 0)
//       {
//         chr->pcdata->prompt = 1;
//         set_it_up (chr);
//         return;
//       }
//     else
//       {
//         chr->pcdata->prompt = 0;
//         do_clear (chr, "");
//         return;
//       }
//   }
///*
//   else if ( !str_cmp( arg, "nomove" ) ) bit = PLR_BLANKPROMPT;
// */
//      else if (!str_cmp (arg, "brief"))
//   bit = PLR_BRIEF;
//      else if (!str_cmp (arg, "combine"))
//   bit = PLR_COMBINE;
//      else if (IS_IMMORTAL (chr) && !str_cmp (arg, "holylag"))
//   bit = PLR_HOLYLAG;
//      else if (!str_cmp (arg, "prompt"))
//   bit = PLR_PROMPT;
//      else if (!str_cmp (arg, "upprompt"))
//   bit = PLR_PROMPT_UP;
//      else if (!str_cmp (arg, "ansi"))
//   bit = PLR_ANSI;
//      else
//   {
//     if (!str_cmp (arg, "challenge") || !str_cmp (arg, "challnge"))
//       {
//         if (IS_MOB (chr))
//      return;
//         if (chr->pcdata->challenge_on)
//      {
//        send_to_char ("Challenges toggled \x1B[30;1mOFF\x1B[37;0m.\n\r", chr);
//        chr->pcdata->challenge_on = FALSE;
//      }
//         else
//      {
//        send_to_char ("Challenges toggled\x1B[1m ON\x1B[0m.\n\r", chr);
//        chr->pcdata->challenge_on = TRUE;
//      }
//         return;
//       }
//     if (!str_cmp (arg, "arena") || !str_cmp (arg, "arenanotfy") || !str_cmp (arg, "arenanotify"))
//       {
//         if (IS_MOB (chr))
//      return;
//         if (chr->pcdata->arena_msg == 2)
//      {
//        send_to_char ("Arena messages toggled \x1B[30;1mOFF\x1B[37;0m.\n\r", chr);
//        chr->pcdata->arena_msg = 0;
//      }
//         else if (chr->pcdata->arena_msg == 1)
//      {
//        send_to_char ("Arena notify will be shown, but not battle spam.\n\r", chr);
//        chr->pcdata->arena_msg = 2;
//      }
//         else
//      {
//        send_to_char ("Arena messages toggled\x1B[1m ON\x1B[0m.\n\r", chr);
//        chr->pcdata->arena_msg = 1;
//      }
//         return;
//       }
//     send_to_char ("Config which option?\n\r", chr);
//     return;
//   }
//      if (fSet)
//   {
//     sprintf (buf, "Enabled.\n\r");
//     SET_BIT (chr->pcdata->act2, bit);
//#ifdef OLD_NOMOVE
//     if (bit == PLR_BLANKPROMPT)
//       {
//         REMOVE_BIT (chr->pcdata->act2, PLR_TELNET_GA);
//         dd.SendTelnetCommand (chr->description, dontecho, 0);
//         dd.SendTelnetCommand (chr->description, echo_off_str, 0);
//         dd.SendTelnetCommand (chr->description, linemode_off, 0);
//         dd.SendTelnetCommand (chr->description, echo_off_str, 0);
//         scrn_upd (chr);
//       }
//#endif
//   }
//      else if (!fSet && arg2[0] == '-')
//   {
//     sprintf (buf, "Disabled.\n\r");
//     REMOVE_BIT (chr->pcdata->act2, bit);
//     if (bit == PLR_BLANKPROMPT && IS_PLAYER (chr))
//       {
//         char tmps[STD_LENGTH];
//         SET_BIT (chr->pcdata->act2, PLR_TELNET_GA);
//         dd.SendTelnetCommand (chr->description, linemode_on, 0);
//         dd.SendTelnetCommand (chr->description, echo_on_str, 0);
//         sprintf (tmps, "\x1B[1;%dr\x1B[2J", chr->pcdata->pagelen);
//         send_to_char (tmps, chr);
//       }
//   }
//      else
//   {
//     if (IS_SET (chr->pcdata->act2, bit))
//       {
//         sprintf (buf, "Toggled \x1B[30;1mOFF\x1B[37;0m.\n\r");
//         REMOVE_BIT (chr->pcdata->act2, bit);
//         if (bit == PLR_BLANKPROMPT && IS_PLAYER (chr))
//      {
//        char tmps[STD_LENGTH];
//        SET_BIT (chr->pcdata->act2, PLR_TELNET_GA);
//        dd.SendTelnetCommand (chr->description, linemode_on, 0);
//        dd.SendTelnetCommand (chr->description, echo_on_str, 0);
//        sprintf (tmps, "\x1B[1;%dr\x1B[2J", chr->pcdata->pagelen);
//        send_to_char (tmps, chr);
//      }
//       }
//     else
//       {
//         SET_BIT (chr->pcdata->act2, bit);
//         sprintf (buf, "Toggled\x1B[1m ON\x1B[0m.\n\r");
//#ifdef OLD_NOMOVE
//         if (bit == PLR_BLANKPROMPT)
//      {
//        REMOVE_BIT (chr->pcdata->act2, PLR_TELNET_GA);
//        dd.SendTelnetCommand (chr->description, dontecho, 0);
//        dd.SendTelnetCommand (chr->description, echo_off_str, 0);
//        dd.SendTelnetCommand (chr->description, linemode_off, 0);
//        dd.SendTelnetCommand (chr->description, echo_off_str, 0);
//        scrn_upd (chr);
//      }
//#endif
//       }
//   }
//      if (bit != PLR_BLANKPROMPT)
//   send_to_char (buf, chr);
//    }
//  return;
//}

//void 
//set_title (CharacterData  chr, string title)
//{
//  char buf[STD_LENGTH];
//  if (IS_MOB (chr))
//    {
//      bug ("Set_title: NPC.", 0);
//      return;
//    }
//  strcpy (buf, title);
///*
//   if ( isalpha(title[0]) || isdigit(title[0]) )
//   {
//   buf[0] = ' ';
//   strcpy( buf+1, title );
//   }
//   else
//   {
//   strcpy( buf, title );
//   }
// */
//  free_string (chr->pcdata->title);
//  chr->pcdata->title = str_dup (buf);
//  return;
//}

//void 
//do_title (CharacterData  chr, string szUserArguments)
//{
//  char buf[STD_LENGTH];
//  string t;
//  DEFINE_COMMAND ("title", do_title, POSITION_DEAD, 0, NORMAL, "This command allows you to change your title.")

//    if (IS_MOB (chr))
//    return;
//  if (szUserArguments[0] == '\0')
//    {
//      send_to_char ("Change your title to what?\n\r", chr);
//      return;
//    }
//  if (strlen (szUserArguments) > 60)
//    {
//      send_to_char ("Your title may not be MoreRoomInfo than 60 CharactersInRoom.\n\r", chr);
//      return;
//    }
//  for (t = szUserArguments; *t != '\0'; t++)
//    {
//      if (*t == '$' && *(t + 1) != '\0' && (*(t + 1) == 'F' || *(t + 1) == 'f'))
//   {
//     send_to_char ("Sorry, no flashing titles.\n\r", chr);
//     return;
//   }
//    }
//  sprintf (buf, "%s\x1B[37;0m", anseval (szUserArguments, chr));
///* buf[26] = '\0'; */
///* smash_tilde( buf ); */
//  set_title (chr, buf);
//  send_to_char ("Title set.\n\r", chr);
//  return;
//}

//void 
//do_description (CharacterData  chr, string szUserArguments)
//{
//  int k;
//  int countcr;
//  DEFINE_COMMAND ("description", do_description, POSITION_DEAD, 0, NORMAL, "This command allows you to type in your character's description.")

//    k = 0;
//  countcr = 0;
//  if (IS_MOB (chr))
//    return;
//  string_append (chr, &chr->pcdata->description);
///*if (chr->description!=NULL) {
//   for (t=chr->description; *t!='\0'; t++) {
//   if (*t=='\n') countcr++;
//   k++;
//   if (countcr>15 || k>790) {
//   char tp[800];
//   *t='\0';
//   send_to_char("Description too long! Sorry!\n\r",chr);
//   strcpy(tp,chr->description);
//   free_string(chr->description);
//   chr->description=str_dup(tp);
//   break;
//   }
//   }
//   }
// */
///*
//   if ( szUserArguments[0] != '\0' )
//   {
//   buf[0] = '\0';
//   smash_tilde( szUserArguments );
//   if ( szUserArguments[0] == '+' )
//   {
//   if ( STR(chr, description) != NULL )
//   strcat( buf, STR(chr, description) );
//   szUserArguments++;
//   while ( isspace(*szUserArguments) )
//   szUserArguments++;
//   }
//   if ( strlen(buf) + strlen(szUserArguments) >= STD_LENGTH - 500 )
//   {
//   send_to_char( "Description too long.\n\r", chr );
//   return;
//   }
//   strcpy(tdesc,buf);
//   for (k=0; k<(STD_LENGTH+10) ;k++)
//   {
//   if (tdesc[k]=='\0') break;
//   if (tdesc[k]=='\n') countcr++;
//   }
//   if (countcr>10) 
//   {
//   send_to_char("You description can only be 10 lines maximum.\n\r",chr);
//   return;
//   }
//   strcat( buf, szUserArguments );
//   strcat( buf, "\n\r" );
//   free_string( chr->description );
//   chr->description = str_dup( buf );
//   }
//   send_to_char( "Your description is:\n\r", chr );
//   send_to_char( chr->description ? chr->description : "(None).\n\r", chr );
// */
//  return;
//}


// OLD CODE to PORT: "consider" command, etc
//   void 
//do_consider (CharacterData  chr, string szUserArguments)
//{
//  char arg[SML_LENGTH];
//  CharacterData victim;
//  string msg = '\0';
//  int loopcount;
//  int ctemp_hps;
//  int vtemp_hps;
//  DEFINE_COMMAND ("consider", do_consider, POSITION_RESTING, 0, NORMAL, "This command runs through the battle in your character's mind, and tells you the suspected outcome.")

//    one_argy (szUserArguments, arg);
//  if (arg[0] == '\0')
//    {
//      send_to_char ("Consider killing whom?\n\r", chr);
//      return;
//    }
//  if ((victim = get_char_room (chr, arg)) == NULL)
//    {
//      send_to_char ("They're not here.\n\r", chr);
//      return;
//    }
//  currentActionsAndBehavior ("You carefully go over the battle in your mind...", chr, NULL, victim, TO_CHAR);
//  ctemp_hps = chr->HPCurrent;
//  vtemp_hps = victim->HPCurrent;
//  for (loopcount = 0; ((ctemp_hps >= 0) && (vtemp_hps >= 0)); ++loopcount)
//    {
//      multi_hit (victim, chr, TYPE_UNDEFINED + 10000);
//      ctemp_hps -= cons_damage;
//      multi_hit (chr, victim, TYPE_UNDEFINED + 10000);
//      vtemp_hps -= cons_damage;
//    }
///*OKAY... one of them has been simulated as dead.. now calc stats */
//  if ((vtemp_hps <= 0) && (ctemp_hps <= 0))
//    {
//      currentActionsAndBehavior ("This would be a totally even battle.", chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if (vtemp_hps == 0)
//    vtemp_hps = -1;
//  if (ctemp_hps == 0)
//    ctemp_hps = 1;
//  if ((vtemp_hps <= 0) && (ctemp_hps >= 0))
//    {
//      if (ctemp_hps < (chr->HPMax / 15))
//   msg = "You are almost exactly evenly matched (without offensive magic)";
//      else if (ctemp_hps < (chr->HPMax / 10))
//   msg = "It would be a close battle without offensive magic.";
//      else if (ctemp_hps < (chr->HPMax / 7))
//   msg = "It would be a close battle but you would probably win.";
//      else if (ctemp_hps < (chr->HPMax / 5))
//   msg = "You would probably win unless $N has some tricks up $S sleeve.";
//      else if (ctemp_hps < (chr->HPMax / 4))
//   msg = "You should be able to beat $N unless $E has some tricks up $S sleeve.";
//      else if (ctemp_hps < (chr->HPMax / 2))
//   msg = "This should be fairly easy...";
//      else if (ctemp_hps < (chr->HPMax - (chr->HPMax / 2)))
//   msg = "No sweat... a little work and $N will go down hard...";
//      else
//   {
//     if (ctemp_hps < (chr->HPMax - 60))
//       msg = "$N stands no chance against you.";
//     else if (ctemp_hps < (chr->HPMax - 25))
//       msg = "Why would you bore yourself killing $N...";
//     else
//       msg = "You will have fun rearranging $N's bodyparts!";
//   }
//      currentActionsAndBehavior (msg, chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if ((ctemp_hps < 0) && (vtemp_hps > 0))
//    {
//      if (vtemp_hps < (victim->HPMax / 15))
//   msg = "You are almost exactly evenly matched.";
//      else if (vtemp_hps < (victim->HPMax / 10))
//   msg = "It would be a close battle but you would probably lose.";
//      else if (vtemp_hps < (victim->HPMax / 7))
//   msg = "You would need a little luck.";
//      else if (vtemp_hps < (victim->HPMax / 5))
//   msg = "You would need quite a bit of luck.";
//      else if (vtemp_hps < (victim->HPMax / 4))
//   msg = "$N will probably beat you in a one on one battle.";
//      else if (vtemp_hps < (victim->HPMax / 2))
//   msg = "You'd probably need a friend or two...";
//      else if (vtemp_hps < (victim->HPMax - (victim->HPMax / 2)))
//   msg = "You better have brought some friends!";
//      else if (vtemp_hps < (victim->HPMax - (victim->HPMax / 3)))
//   msg = "You better have brought A LOT of friends!";
//      else if (vtemp_hps < (victim->HPMax - (victim->HPMax / 4)))
//   msg = "I hope you have an army to back you up!";
//      else
//   {
//     if (vtemp_hps < (victim->HPMax - 60))
//       msg = "$N will laugh as $E rips you in two.";
//     else if (vtemp_hps < (victim->HPMax - 25))
//       msg = "$N will squish your face into the ground with ease.";
//     else
//       msg = "You truly are a masochist! There is NO WAY!";
//   }
//      currentActionsAndBehavior (msg, chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  return;
//}

//void 
//do_group_consider (CharacterData  chr, string szUserArguments)
//{
//  char arg[SML_LENGTH];
//  CharacterData victim;
//  CharacterData attacker;
//  string msg = '\0';
//  int loopcount;
//  int ctemp_hps;
//  int vtemp_hps;
//  DEFINE_COMMAND ("gconsider", do_group_consider, POSITION_RESTING, 0, NORMAL, "This command runs through the battle in your character's mind as if you were the tank for your group, and tells you the suspected outcome.")
//    one_argy (szUserArguments, arg);
//  if (chars_in_group (chr) < 2)
//    {
//      send_to_char ("But you aren't in a group!!\n\r", chr);
//      return;
//    }
//  if (arg[0] == '\0')
//    {
//      send_to_char ("Group-Consider killing whom?\n\r", chr);
//      return;
//    }
//  if ((victim = get_char_room (chr, arg)) == NULL)
//    {
//      send_to_char ("They're not here.\n\r", chr);
//      return;
//    }
//  currentActionsAndBehavior ("You carefully go over the battle in your mind...", chr, NULL, victim, TO_CHAR);
//  ctemp_hps = chr->HPCurrent;
//  vtemp_hps = victim->HPCurrent;
//  check_room_more (chr->inRoom);
//  for (loopcount = 0; ((ctemp_hps >= 0) && (vtemp_hps >= 0)); ++loopcount)
//    {
//      multi_hit (victim, chr, TYPE_UNDEFINED + 10000);
//      ctemp_hps -= cons_damage;
//      for (attacker = chr->inRoom->MoreRoomInfo->people; attacker != NULL; attacker = attacker->next_in_room)
//   {
//     if (attacker == chr || is_same_group (attacker, chr))
//       {
//         multi_hit (attacker, victim, TYPE_UNDEFINED + 10000);
//         vtemp_hps -= cons_damage;
//       }
//   }
//    }
///*OKAY... one of them has been simulated as dead.. now calc stats */
//  if ((vtemp_hps <= 0) && (ctemp_hps <= 0))
//    {
//      currentActionsAndBehavior ("This would be a totally even battle.", chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if (vtemp_hps == 0)
//    vtemp_hps = -1;
//  if (ctemp_hps == 0)
//    ctemp_hps = 1;
//  if ((vtemp_hps <= 0) && (ctemp_hps >= 0))
//    {
//      if (ctemp_hps < (chr->HPMax / 15))
//   msg = "Your group and the mob are almost exactly evenly matched.";
//      else if (ctemp_hps < (chr->HPMax / 10))
//   msg = "It would be a close battle without offensive magic.";
//      else if (ctemp_hps < (chr->HPMax / 7))
//   msg = "It would be a close battle but your group would probably win.";
//      else if (ctemp_hps < (chr->HPMax / 5))
//   msg = "Your group would probably win but it might be close.";
//      else if (ctemp_hps < (chr->HPMax / 4))
//   msg = "Your group should be able to beat $N.";
//      else if (ctemp_hps < (chr->HPMax / 2))
//   msg = "This should be fairly easy...";
//      else if (ctemp_hps < (chr->HPMax - (chr->HPMax / 2)))
//   msg = "A little teamwork and $N will go down hard...";
//      else
//   {
//     if (ctemp_hps < (chr->HPMax - 60))
//       msg = "$N stands no chance against your group.";
//     else if (ctemp_hps < (chr->HPMax - 25))
//       msg = "Why would your group bore itself with $N...";
//     else
//       msg = "Your group will have fun ripping off $N's bodyparts!";
//   }
//      currentActionsAndBehavior (msg, chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  if ((ctemp_hps < 0) && (vtemp_hps > 0))
//    {
//      if (vtemp_hps < (victim->HPMax / 15))
//   msg = "The mob might take you out before your group wins.";
//      else if (vtemp_hps < (victim->HPMax / 10))
//   msg = "You will probably die, but your group should win.";
//      else if (vtemp_hps < (victim->HPMax / 7))
//   msg = "You would need a little luck tanking this foe.";
//      else if (vtemp_hps < (victim->HPMax / 5))
//   msg = "Your group probably will win, but you will might die in the process.";
//      else if (vtemp_hps < (victim->HPMax / 4))
//   msg = "Your group may win, but you will probably die in the battle.";
//      else if (vtemp_hps < (victim->HPMax / 2))
//   msg = "You will probably die, but your group still stands a small chance.";
//      else if (vtemp_hps < (victim->HPMax - (victim->HPMax / 2)))
//   msg = "You will probably have to flee, as will others in your group.";
//      else if (vtemp_hps < (victim->HPMax - (victim->HPMax / 3)))
//   msg = "Your group probably will have to flee unless you get lucky.";
//      else if (vtemp_hps < (victim->HPMax - (victim->HPMax / 4)))
//   msg = "$N will probably triumph over your group!";
//      else
//   {
//     if (vtemp_hps < (victim->HPMax - 60))
//       msg = "$N will laugh as $E rips all of you apart.";
//     else if (vtemp_hps < (victim->HPMax - 25))
//       msg = "$N will crush your group with ease.";
//     else
//       msg = "$N could destroy your group with ease!";
//   }
//      currentActionsAndBehavior (msg, chr, NULL, victim, TO_CHAR);
//      return;
//    }
//  return;
//}


// TODO: OLD CODE to PORT:  Pets

//void 
//place_pets (CharacterData  chr)
//{
//  int k;
//  PROTOTYPE *mid;
//  CharacterData mob;
//  if (IS_MOB (chr))
//    return;
//  for (k = 0; k < 20; k++)
//    {
//      if (chr->pcdata->pet_temp[k] != 0)
//   {
//     if ((mid = get_mob_index (chr->pcdata->pet_temp[k])) == NULL)
//       {
//         chr->pcdata->pet_temp[k] = 0;
//         continue;
//       }
//     mob = create_mobile (mid);
//     char_to_room (mob, chr->inRoom);
//     chr->pcdata->number_pets++;
//     mob->HPCurrent = chr->pcdata->pet_hps[k];
//     mob->MPCurrent = chr->pcdata->pet_move[k];
//     SET_BIT (mob->currentlyAffectedBy, AFF_CHARM);
//     SET_BIT (mob->currentActionsAndBehavior, ACT_PET);
//     add_follower (mob, chr);
//   }
//    }
//  return;
//}
